Docker杂谈
一、为什么要用容器
1、上线流程繁琐
传统的项目上线要经历开发—测试—申请资源—审批—部署—测试等环节
2、资源利用率低
普通服务器利用率低,造成过多浪费(低于过20%的开销的服务不在少数)
3、扩容/缩容不及时
业务高峰和低谷扩容/缩容流程繁琐,不能及时有效的处理
4、服务器环境臃肿
为了节约资源,一台服务器跑了N多个项目,而且的项目历史悠久,换了一波又一波维护人员,对维护、迁移带来各种困难(有些历史项目没人敢动)
5、环境不一致
通常线上出了问题,研发的口头禅是:我本地是正常的,到了你的环境就出问题了,肯定是你运维的环境问题,各种甩锅此批彼伏...
二、Docker是什么
- 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源
- 是一种基于操作系统级的虚拟化技术
- 依赖于Linux内核特性,Namespace(资源隔离)和Cgroups(资源限制)
- 一个简单的应用程序打包工具,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,解决了传统项目因环境不一致产生的各种问
三、Docker的核心组件
- Docker Daemon:docker的守护进程,负责与Docker Client交互,并管理镜像、容器实例
- 镜像:类似于重装系统的ISO或ghost文件。同样的docker中的镜像也是系统(可能少了内核)和一些软件或者服务的结合体,通过镜像我们可以运行很多个容器
- 容器:docker的运行实例,如果把镜像看作是maven的打包阶段,那么容器就是打出来的jar包运行的结果
- 仓库:存放镜像的地方。分为公有仓库(docker hub) 和私有仓库
- Containerd:是一个简单的守护进程,向上给Docker Daemon提供接口,向下通过containerd-shim结合runC管理容器
-
- /usr/bin/containerd
- /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
- containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/df1a012ccfbb0192ceb7368c80ac9c51426d83a9eb7b2e962f33fa09d6ce6274 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
- runC:一个命令行工具,它根据OCI标准来创建和运行容器
三、docker和虚拟机的区别
虚拟机:
- 基础设施:它可以是个人电脑、数据中心的服务器,亦或者是云主机
- 主操作系统:俗称宿主机系统,可以macOS、windows或者某个Linux发行版
- 虚拟机管理系统:利用Hypervisor,可以在主操作系统上运行多个不同的从操作系统,比如macOS的HypeKit,支持Windows的Hyper-V以及支持Linux的KVM,还有windows上的virtualBox和VMware 硬件级的EXSI
- Guest OS:假设需要运行相互隔离的应用,则需要使用Hypervisor启动三个GuestOS,也就是三个虚拟机,这些虚拟机都非常大,会消耗宿主机的各种资源
- 各种依赖:每个GuestOS是一个全新的操作系统,需要安装各种依赖
- 系统级隔离:每个GuestOS完全隔离
Docker:
- 主操作系统:所有主流Linux发行版都可以运行Docker,对于macOS和Windows也有一些办法运行docker
- Docker守护进程:Docker取代了Hypervisor,它是运行在操作系统之上的后台进程,负责管理docker容器
- 各种依赖:对于docker,应用所有的依赖都打包在Docker镜像中,docker容器基于docker镜像创建的
- 应用:应用的源代码与它所需的依赖都打包在镜像中,保证了运行环境的一致性
- 进程级隔离:不同应用运行不同的容器中,它们是相互隔离的
Docker有着小巧、迁移部署快速、运行高效等特点,但隔离性比服务器虚拟化差:不同的集装箱属于不同的运单(Docker上运行不同的应用实例),相互独立(隔离)。但由同一个库管人员管理(主机操作系统内核),因此通过库管人员可以看到所有集装箱的相关信息(因为共享操作系统内核,因此相关信息会共享)。
虚拟化就好比在码头上(物理主机及虚拟化层),建立了多个独立的“小码头”—仓库(虚拟机)。其拥有完全独立(隔离)的空间,属于不同的客户(虚拟机所有者)。每个仓库有各自的库管人员(当前虚拟机的操作系统内核),无法管理其它仓库。不存在信息共享的情况
因此,我们需要根据不同的应用场景和需求采用不同的方式使用Docker技术或使用服务器虚拟化技术。例如一个典型的Docker应用场景是当主机上的Docker实例属于单一用户的情况下,在保证安全的同时可以充分发挥Docker的技术优势。对于隔离要求较高的环境如混合用户环境,就可以使用服务器虚拟化技术。正则科技提供了丰富的Docker应用实例,满足您的各种应用需求,并且支持在已经安装了自在(Isvara)服务器虚拟化软件的主机上同时使用服务器虚拟化技术和Docker技术提供不同技术场景。
四、docker安装
docker版本
- 社区版(Community Edition CE)
- 企业版(Enterprise Editon EE)
支持平台
- 各种发型版的Linux
- Mac
- Windows
# 安装依赖包 yum install -y yum-utils
# 添加Docker软件包源 yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
# 安装Docker CE yum install -y docker-ce
# 启动Docker服务并设置开机启动 systemctl start docker systemctl enable docker
https://docs.docker.com/engine/install/centos/ 官方文档:https://docs.docker.com 阿里云源:http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
五、镜像管理
1.镜像是什么
-
- 一个分层存储的文件,不是一个单一的文件
- 一个项目完整运行环境
- 一个镜像可以创建多个容器
- 一种标准化交付
- 一个不包含Linux内核而又精简的Linux操作系统
2.镜像从哪里来
Docker Hub是有Docker公司负责维护的公共镜像仓库,包含大量的容器镜像,Docker工具默认从这个公共镜像库获取 地址:https://hub.docker.com/ 配置镜像加速器 以阿里云为例: 登录控制台—容器镜像服务—镜像加速器 此页面可以看到加速器的地址 cat /etc/docker/daemon.json { "registry-mirrors": ["https://knh15e9b.mirror.aliyuncs.com"] }
3.镜像与容器的联系
4,镜像常用的管理命令
Usage: docker image COMMAND Manage images Commands: build Build an image from a Dockerfile #构建来自Dockerfile history Show the history of an image #查看镜像历史(层级) import Import the contents from a tarball to create a filesystem image # 导入容器文件系统tar归档文件并创建镜像 inspect Display detailed information on one or more images # 显示镜像的详细信息 load Load an image from a tar archive or STDIN #加载镜像来自tar归档的或标准输入 ls List images #列出当前系统上的镜像 prune Remove unused images #移除没有标记或者没有任何容器引用的镜像 pull Pull an image or a repository from a registry #从镜像仓库拉取镜像 push Push an image or a repository to a registry #推送镜像到镜像仓库 rm Remove one or more images #删除一个或多个镜像 save Save one or more images to a tar archive (streamed to STDOUT by default) # 保存一个或多个镜像到tar归档文件 tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE #创建一个引用源镜像标记目标镜像
5.镜像存储的核心技术1:联合文件系统(UnionFS)
-
- Union文件系统是一种分层、轻量级并且高性能的文件系统
- 它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下
- Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像可以制作各种具体的应用镜像
- 镜像是只读的 如果要修改镜像内容,需要通过dockerfile重新打包
[ { "Id": "sha256:f35646e83998b844c3f067e5a2cff84cdf0967627031aeda3042d78996b68d35", "RepoTags": [ "nginx:latest" ], "RepoDigests": [ "nginx@sha256:ed7f815851b5299f616220a63edac69a4cc200e7f536a56e421988da82e44ed8" ], "Parent": "", "Comment": "", "Created": "2020-10-13T08:39:44.146921461Z", "Container": "30fd95c5c49c51e06f02efdb7f6cf22adc04ac7e88eb0ccd0ec3e3f40adae506", "ContainerConfig": { "Hostname": "30fd95c5c49c", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "80/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NGINX_VERSION=1.19.3", "NJS_VERSION=0.4.4", "PKG_RELEASE=1~buster" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"nginx\" \"-g\" \"daemon off;\"]" ], "ArgsEscaped": true, "Image": "sha256:f85f5bff1b6ddc8f428f8528f19c24e9c2284fec8ce02dbc1899b971f4b525cf", "Volumes": null, "WorkingDir": "", "Entrypoint": [ "/docker-entrypoint.sh" ], "OnBuild": null, "Labels": { "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>" }, "StopSignal": "SIGTERM" }, "DockerVersion": "18.09.7", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "80/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NGINX_VERSION=1.19.3", "NJS_VERSION=0.4.4", "PKG_RELEASE=1~buster" ], "Cmd": [ "nginx", "-g", "daemon off;" ], "ArgsEscaped": true, "Image": "sha256:f85f5bff1b6ddc8f428f8528f19c24e9c2284fec8ce02dbc1899b971f4b525cf", "Volumes": null, "WorkingDir": "", "Entrypoint": [ "/docker-entrypoint.sh" ], "OnBuild": null, "Labels": { "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>" }, "StopSignal": "SIGTERM" }, "Architecture": "amd64", "Os": "linux", "Size": 132861270, "VirtualSize": 132861270, "GraphDriver": { "Data": { "LowerDir": "/data/docker/overlay2/9a7891c56c2c5d6dce8e6ea6908f46457bf3073c1750fa4e2f83da5ecebac600/diff:/data/docker/overlay2/b882d0d8e96dc7e32eaa9692c2668dc267b8593a9003ee7839934db27b4114c7/diff:/data/docker/overlay2/46e4bd643cdd4ad59126fb76f42c36ca80c7211049e462411e41c6659c2ec1b5/diff:/data/docker/overlay2/228cf784c84527507350240ac39d525961ec00c0faace0c26e3fab1c799da5b9/diff", "MergedDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/merged", "UpperDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/diff", "WorkDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/work" }, "Name": "overlay2" }, "RootFS": { "Type": "layers", "Layers": [ "sha256:d0fe97fa8b8cefdffcef1d62b65aba51a6c87b6679628a2b50fc6a7a579f764c", "sha256:f14cffae5c1add412127e0704008bb8e730773c0945345c9ea61b7e6eabea8e5", "sha256:280ddd108a0a0ef53ed20d6715facc1cdd9497ef05cad03c3e5b73521a588511", "sha256:fe08d9d9f18556ca241f00b6efd6c7b25767463084e14c05da9e535c0782409c", "sha256:cdd1d8ebeb066bd40f9be824201afe18f0d4fe93b8462353921f0277c09e1289" ] }, "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z" } } ]
6.镜像存储的核心技术2:写时复制(COW)
-
- 当docker第一次启动容器时,初始读写层是空的。当文件系统发生变化时,这些变化都会应用到读写层
- 需要修改容器层(读写)里的文件时,会先把镜像里要写的文件复制到自己的文件系统中进行修改,这个机制就是写时复制(Copy-On-Write)
- 写时复制配合分层机制减少了镜像对磁盘空间的占用和容器启动时间。
"GraphDriver": { "Data": { "LowerDir": "/data/docker/overlay2/9a7891c56c2c5d6dce8e6ea6908f46457bf3073c1750fa4e2f83da5ecebac600/diff:/data/docker/overlay2/b882d0d8e96dc7e32eaa9692c2668dc267b8593a9003ee7839934db27b4114c7/diff:/data/docker/overlay2/46e4bd643cdd4ad59126fb76f42c36ca80c7211049e462411e41c6659c2ec1b5/diff:/data/docker/overlay2/228cf784c84527507350240ac39d525961ec00c0faace0c26e3fab1c799da5b9/diff", "MergedDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/merged", "UpperDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/diff", "WorkDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/work" }, "Name": "overlay2" } LowerDir:镜像层 这一层只读 UpperDir:容器层 这一层可读写 MergeDir:挂载点 当文件系统挂载后,在merge目录下将同时看到来自各lower和upper目录下的内容,并且用户无法(无需)感知这些文件分别来自lower,哪些来自upper,用户看见的只是一个普通的文件系统根目录而已
联合文件系统和写时复制原理都是由overlay2文件存储驱动来实现的 docker info |grep Stor Storage Driver: overlay2
六、容器管理
1.创建容器的常用选项
2.创建容器时可以根据实际情况做资源限制
docker run -itd --name centos-init --memory="1024m" --memory-swap="2048m" --oom-kill-disable centos docker ps -a | awk '{print $1,$NF}'|grep centos-init 70e98a309acc centos-init docker stats 70e98a309acc CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 70e98a309acc centos-init 0.00% 1.52MiB / 1GiB 0.15% 0B / 0B 0B / 0B 1
#内存限制已生效
OOM事件
OOM(Out Of Memory)内存不足,通常是由于某些不稳定的进程占用过多的内存造成,在Docker中称为OOM事件,当容器使用的内存过多时就会发生OOM事件,
这个事件是由Linux内核的内存管理机制发起,并将是使用占用内存过多的容器Kill掉,保证系统的可持续运行。Linux内核为了保证系统的稳定性而将内存划分为两大部分用户空间与内核空间
用户空间是提供给用户进程所使用的内存空间。内核空间是仅提供给内核运行的空间。用户的进程是无法访问内核空间,而内核是可以访问用户空间与内核空间。
3.管理容器
# cp 宿主机和容器之间互拷贝文件 Usage: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH Options: -a, --archive Archive mode (copy all uid/gid information) -L, --follow-link Always follow symbol link in SRC_PATH # exec 在容器里执行命令 1).进入容器 docker exec -it 容器id/NAMES /bin/bash
4.NameSpace
在容器化中,一台物理机可以运行多个不同的操作系统,那就需要解决"隔离性”,彼此感知不到对方的存在,有问题互不影响 Linux内核从2.4.19版本开始引入namespace概念,其目的是将特定的全局系统资源通过抽象方法使得namespace中的进程看起来拥有自己的隔离资源。docker就是借助这个机制实现了容器资源的隔离 Linux的NameSpace机制提供了6种不同命名空间: IPC:隔离进程间通信 MOUNT:隔离文件系统挂载点(一个容器是一个独立的操作系统) NET:隔离网络协议栈 PID:隔离进程号,进程命名空间是一个父子结构,子空间对父空间可见 USER:隔离用户 UTS:隔离主机名和域名
ls /proc/$$/ns
ipc mnt net pid user uts
5.CGroups
docker利用namespace实现了容器隔离,但是namespace不能对容器做资源限制,比如cpu、内存 如果某一个容器属于CPU密集型任务,那么会影响其他容器使用CPU,导致多个容器相互影响并抢占资源,这就要用到CGroups(Control Groups),限制容器资源 CGroups:所有的任务就是运行在系统中的一个进程,而CGroups以某种标准将一组目标进行资源分配和控制,例如CPU、memory、net等,并且可以动态配置 docker update --help Usage: docker update [OPTIONS] CONTAINER [CONTAINER...] Update configuration of one or more containers Options: --blkio-weight uint16 Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) --cpu-period int Limit CPU CFS (Completely Fair Scheduler) period --cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota --cpu-rt-period int Limit the CPU real-time period in microseconds --cpu-rt-runtime int Limit the CPU real-time runtime in microseconds -c, --cpu-shares int CPU shares (relative weight) --cpus decimal Number of CPUs --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) --kernel-memory bytes Kernel memory limit -m, --memory bytes Memory limit --memory-reservation bytes Memory soft limit --memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap --pids-limit int Tune container pids limit (set -1 for unlimited) --restart string Restart policy to apply when a container exits CGroups主要功能: 限制进程组使用的资源数量:可以为进程组设定使用上限,例如内存 进程组优先控制:可以为进程组分配特定的CPU、磁盘io吞吐量 记录进程组使用的资源数量:例如记录某个进程组使用的CPU时间 进程组控制:可以将进程组挂起和恢复 # 查看cgroups可控制的资源:ll /sys/fs/cgroup/ blkio:块设备io cpu:限制CPU时间片的分配,与cpuacct挂载同一目录 cpuacct:生成cgroup中的任务占用cpu资源的报告,与CPU挂载同一目录 cpuset:给cgroup中的任务分配独立的CPU和内存节点 devices:允许或拒绝cgroup中的任务访问设备 freezer:暂停/恢复cgroup中的任务 hugetlb:限制使用的内存页数量 memory:对cgroup中任务的可用内存进行控制,兵自动生成资源占用报告 net_cls:使用等级标识符标记网络数据包,这让Linux流量控制程序可以识别来自特定cgroup任务的数据包,并进行网络限制 net_prio:允许基于cgroup设置网络流量优先级 perf_event:允许使用perf工具来监控cgroup pids:限制任务数量 容器实际资源限制位置: /sys/fs/cgroup/<资源名>/docker/<容器ID>
七、容器数据持久化
docker提供三种方式将数据从宿主机挂载到容器中: volumes:docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)
bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中
tmpfs:挂载存储在主机系统的内存中,而不会写入宿主机文件系统。如果不希望将数据持久化存储,可以使用tmpfs,同时避免写入容器可写层提高性能
1.volumes
由docker负责创建、管理。docker volume
默认情况下创建的volume本质上还是宿主机文件系统的一个目录,与普通目录无本质区别。
一个volume可以同时供多个container使用,如果没有container使用volume,它不会自动删除,需要运行docker volume prune明确删除
通过使用第三方提供的volume driver,用户可以将数据持久化到远程主机或者云存储中,也就是说存储空间可以不由宿主机提供
docker volume --help Usage: docker volume COMMAND Manage volumes Commands: create Create a volume inspect Display detailed information on one or more volumes ls List volumes prune Remove all unused local volumes rm Remove one or more volumes
# 创建volume docker volume create nginx-vol # 查看volume的详细信息 docker volume inspect nginx-vol [ { "CreatedAt": "2020-11-10T16:37:22+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/data/docker/volumes/nginx-vol/_data", "Name": "nginx-vol", "Options": {}, "Scope": "local" } ] # 如果修改了Docker Root的目录,则对应相关目录都会被修改 # 用volume创建个容器 docker run -itd --name nginx --mount src=nginx-vol,dst=/usr/share/nginx/html nginx docker run -itd --name nginx -v nginx-vol:/usr/share/nginx/html nginx # 删除volume docker stop nginx # 停止使用该卷的容器 docker rm -f nginx # 删除使用该卷的容器 docker volume rm nginx-vol # 再删除此卷
# 如果指定的卷不存在,则自动创建
2.bind mounts
本质上是宿主机、container之间共享宿主机文件系统。这种持久化的方法更导致container与宿主机的偶合过于紧密,所以不推荐使用
# 用卷创建一个容器 docker run -itd --name=nginx --mount type=bind,src=/root/www,dst=/usr/share/nginx/html nginx docker run -itd --name=nginx1 -v /root/www:/usr/share/nginx/html nginx # 验证 docker inspect nginx [ { "Id": "324328596c9bbdb97c436b0399147d68a484ca6764f8fe34403a794b1c44ffbc", "Created": "2020-11-10T09:03:08.761761701Z", "Path": "/docker-entrypoint.sh", "Args": [ "nginx", "-g", "daemon off;" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 6828, "ExitCode": 0, "Error": "", "StartedAt": "2020-11-10T09:03:09.281253027Z", "FinishedAt": "0001-01-01T00:00:00Z" }, .......... "Mounts": [ { "Type": "bind", "Source": "/root/www", "Destination": "/usr/share/nginx/html", "Mode": "", "RW": true, "Propagation": "rprivate" } ], ........... ]
# 如果源文件/目录没有存在,会报错,如下
docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /root/www.
# 如果目标在容器中是非空目录,则该目录现有内容被隐藏
应用场景
volume: • 多个运行容器之间共享数据, 多个容器可以同时挂载相同的卷。 • 当容器停止或被移除时,该卷依然存在。 • 当明确删除卷时, 卷才会被删除。 • 将容器的数据存储在远程主机或其他存储上(间接) • 将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录(/var/lib/docker/volumes/) bind mounts • 从主机共享配置文件到容器。默认情况下,挂载主机/etc/resolv.conf到每个容器,提供DNS解析。 • 在Docker主机上的开发环境和容器之间共享源代码。例如,可以将Maven target目录挂载到容器中,每次在Docker主机 上构建Maven项目时,容器都可以访问构建的项目包。 • 当Docker主机的文件或目录结构保证与容器所需的绑定挂载一致时 tmpfs: 有特定的应用场景。比如docker可将用户名与密码等敏感数据保存在某个数据库中,当启动需要访问这些敏感数据的container或者service时,docker会在宿主机上创建一个tmpfs,然后将敏感数据从数据库读出写到tmpfs中,再将tmpfs mount到container中,安样能保证数据安全。当容器停止运行时,则相应的tmpfs也从系统中删除
八、docker容器网络
1.四种网络模式
docker network --help Usage: docker network COMMAND Manage networks Commands: connect Connect a container to a network create Create a network disconnect Disconnect a container from a network inspect Display detailed information on one or more networks ls List networks prune Remove all unused networks rm Remove one or more networks Run 'docker network COMMAND --help' for more information on a command.
- bridge
-network=bridge
默认网络,docker启动后会创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
也可以自定义网络,相比默认的具备内部dns发现,可以通过容器名之间通信
- host
-network=host
容器不会获得一个独立的notwork namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主机的。容器除了网络都,其他都是隔离的
- none
--network=none
获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置
- container
--network=container:Name/ID
与指定容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都是隔离的
2.docker网络模型
- veth pair
成对出现的一种虚拟设备,数据从一端进,从另一端出。用于解决网络命名空间之间的隔离,每启动一个容器就会对应启动一个veth
- docker0
网桥是一个二层网络设备,通过网桥可以将Linux支持的不同端口连接起来,并实现类似交换机那样的多对多的通信
3、容器网络访问原理
九、定制容器镜像
DockerFile常用指令
- FROM
构建新镜像是基于哪个镜像
FROM centos:latest
- RUN
构建镜像时运行的shell命令
shell格式:
RUN <命令行命令> # <命令行命令> 等同于,在终端操作的 shell 命令。
RUN yum install wget -y
exec格式:
RUN ["可执行文件","参数1","参数2"]
RUN ["run.sh","release","V0.2"] #等同于./run.sh release V0.2
*****注意:Dockerfile的指令每执行一次都会在docker上新建一层,所以过多无意义的层,会造成镜像膨胀过大,可以把要执行的shell命令通过&&连接起来放在一行执行
- CMD
类似于RUN指令,用于运行程序,但二者运行的时间点不同
-
- CMD在docker run时运行
- RUN在docker build时运行
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD指令指定的程序可被docker run命令行参数中指定要运行的程序覆盖
注意:如果dockerfile中存在多个CMD指令,仅最后一个生效
格式:
-
- CMD [“executable”,“param1”,“param2”] : exec形式(首选)
- CMD [“param1”,“param2”] : 作为ENTRYPOINT的默认参数
- CMD command param1 param2 : Shell形式
- ENTRYPOINT
类似于CMD命令,但其不会被docker run的命令行参数指定的指令所覆盖,而且这些命令行参数会被当做参数传给ENTRYPOINT指令指定的程序
但是,如果运行docker run时使用了--entrypoint选项,此选项的参数可当做要运行的程序覆盖ENTRYPOINT指令指定的程序
优点:在执行docker run的时候可以指定enterpoint运行时所需的参数
注意:如果Dockerfile中存在多个ENTRYPOINT指令,仅最后一个生效
格式:
-
- ENTRYPOINT ["executable", "param1", "param2"]
- ENTRYPOINT command param1 param2
- ENTRYPOINT ["executable", "param1", "param2"]
可以搭配CMD命令使用:一般是变参才会使用CMD,这里的CMD等于是在给ENTRYPOINT传参
可参考:https://www.runoob.com/docker/docker-dockerfile.html
- LABEL
标签:用于描述此镜像的作者以及作用,根据实际情况描述
- EXPOSE
仅仅是声明端口
作用:
-
- 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射
- 在运行时使用随机端口映射时,也就是docker run -p时,会自动映射EXPOSE的端口
- ENV
设置环境变量,可以在后续指令中调用这个环境变量
ENV PATH $PATH:/usr/local/nginx/sbin
示例:
设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
- ADD
解压压缩包并拷贝
格式:
ADD src dest
ADD nginx-1.15.5.tar.gz /
- COPY
拷贝文件或目录到镜像中,一般用于项目镜像(将项目代码打包到镜像中)
格式:
COPY src dest
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
- VOLUME
定义匿名数据卷。在启动容器时忘记挂载数据卷,自动挂载到匿名卷
作用:
-
- 避免重要数据,因容器重启而丢失。这是非常致命的
- 避免容器不断变大。例如日志目录
格式:
VOLUME "目录的绝对路径"
VOLUME "/usr/src/app/release/config" \
"/usr/src/app/release/logs"
- USER
为RUN CMD和ENTRYPOINT执行命令时指定运行用户
- WORKDIR
为RUN CMD ENTRYPOINT COPY 和ADD设置工作目录
docker build构建镜像
Usage: docker build [OPTIONS] PATH | URL | -
Options:
-t --tag list #镜像名称
-f --file string #指定Dockerfile文件的位置 dockerfile可以是远程位置的
# docker build -t shykes/myapp .
# docker build -t shykes/myapp -f /path/Dockerfile /path
# docker build -t shykes/myapp http://www.example.com/Dockerfile
FROM centos:7 LABEL nginx chunke_li RUN rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm && \ yum install nginx -y EXPOSE 80 CMD ["/usr/sbin/nginx","-g","daemon off;"]
docker build -t nginx:v3 -f Dockerfile . Sending build context to Docker daemon 2.048kB Step 1/5 : FROM centos:7 ---> 7e6257c9f8d8 Step 2/5 : LABEL nginx chunke_li ---> Using cache ---> 99791e9a003e Step 3/5 : RUN rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm && yum install nginx -y ---> Using cache ---> 36a9fe459afb Step 4/5 : EXPOSE 80 ---> Using cache ---> 3f0083ee6294 Step 5/5 : CMD ["/usr/sbin/nginx","-g","daemon off;"] ---> Running in 3ed93f11530d Removing intermediate container 3ed93f11530d ---> 46f08f11c53f Successfully built 46f08f11c53f Successfully tagged nginx:v3
编写Dockerfile最佳实践:
- 减少镜像层:一次RUN指令形成新的一层,尽量shell命令都写在一行,减少镜像层
- 优化镜像大小:一次性RUN形成新的一层,如果没有在同一层删除,无论文件是否最后删除,都会带到下一层,所以在每一层清理对应的残留数据,减小镜像大小
- 减少网络传输时间:例如软件包、仓库等
- 多阶段构建:代码编译、部署在一个Dockerfile中完成,指挥保留部署阶段产生数据
- 选择最小的基础镜像:例如alpine