一、Docker 架构Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。Docker 容器通过 Docker 镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。Docker 面向对象容器 对象镜像 类Docker 镜像(Images) Docker 镜像是用于创建 Docker 容器的模板。Docker 容器(Container) 容器是独立运行的一个或一组应用。Docker 客户端(Client) Docker 客户端通过命令行或者其他工具使用 Docker API (https://docs.docker.com/reference/api/docker_remote_api) 与 Docker 的守护进程通信。Docker 主机(Host) 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。Docker 仓库(Registry) Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。Docker Machine Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。Docker项目的目标是实现轻量级的操作系统虚拟化解决方案。Docker的基础是linux容器(LXC)等技术。二、Docker的概念,安装及镜像管理2.1、docker的概念:镜像:是一个只读的模板,类似于安装系统用到的那个iso文件,我们通过镜像来完成各种应用的部署。镜像可以用来创建Docker容器容器:镜像类似于操作系统,而容器类似于虚拟机本身。它可以被启动、开始、停止、删除等操作,每个容器都是相互隔离的。可以把容器看做是一个简易版的linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。仓库:存放镜像的一个场所,仓库分为公开仓库和私有仓库。最大的公开仓库是Docker hub(hub.docker.com),国内公开仓库(dockerpool.com)2.2、docker安装启动:yum install -y epel-releaseyum instal -y dockersystemctl enable docker.servicesystemctl start docker 2.3、镜像管理2.3.1、获取镜像语法:docker pull NAME[:TAG]其中,NAME是镜像仓库的名称(用来区分镜像),TAG是镜像的标签(用来表示版本信息)docker pull centos:从docker.com获取centos镜像2.3.2、查看镜像语法:docker images [root@localhost ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/nginx latest b175e7467d66 2 days ago 109 MB docker tag centos long:为centos镜像设置标签为long,再使用docker images查看会多出来一行,打了标签的image id和centos的一样[root@localhost ~]# docker tag nginx nginx_1.12.2[root@localhost ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/nginx latest b175e7467d66 2 days ago 109 MBnginx_1.12.2 latest b175e7467d66 2 days ago 109 MBdocker inspect {IMAGE_ID | IMAGE_NAME}:获取镜像详细信息[root@localhost ~]# docker inspect nginx返回的是一个JSON格式的消息,如果我们只要其中一项内容时,可以使用参数-f来指定,例如,获取镜像的Architecture[root@localhost ~]# docker inspect -f {{".Architecture"}} nginxamd642.3.3、搜索镜像docker search [image-name]:从docker仓库搜索docker镜像,后面是关键词[root@localhost ~]# docker search nginx2.3.4、删除镜像docker rmi centos:用来删除指定镜像, 其中后面的参数可以是tag,如果是tag时,实际上是删除该tag,只要该镜像还有其他tag,就不会删除该镜像。当后面的参数为镜像ID时,则会彻底删除整个镜像,连通所有标签一同删除[root@localhost ~]# docker rmi nginx_1111Untagged: nginx_1111:latestUntagged: docker.io/nginx@sha256:37350fbb4afbb1c01b6e542fe1537dd701e4430983d6d9c673cbb5eccdbec357docker rmi -f centos:强制删除,一般不建议使用,会导致某些问题[root@localhost ~]# docker rmi -f nginx_1111Untagged: nginx_1111:latest 2.3.5、创建镜像创建镜像的方法有以下3种方式:(1)基于已有镜像的容器创建(2)基于本地模板导入(3)基于Dockerfile创建 (1)基于已有镜像的容器创建命令格式:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]主要选项:-a:作者信息-m:提交消息-p:提交时暂停容器运行运行docker run后,进入到该容器中,我们做一些变更,比如安装一些东西,然后针对这个容器进行创建新的镜像 [root@localhost ~]# docker ps -a //查看所有的容器 [root@localhost ~]# docker start 67d //启动ID为67d的容器,ID可简写为前3位[root@localhost ~]# docker exec -it 67d /bin/bash //进入67d容器[root@67dde53e0651 /]# yum install -y net-tools wget[root@67dde53e0651 /]# exit[root@localhost ~]# docker commit -m "centos_with_nettools_wget" -a "long" 67d centos_with_net //创建新的镜像sha256:90f2a945a44d466c8a8d46dcdd4ab80f9f2aab79761482a1b5839d9ea2cf7904 tips:这个命令有点像svn的提交,-m 加一些改动信息,-a 指定作者相关信息 67d这一串为容器id,再后面为新镜像的名字 [root@localhost ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEcentos_with_net latest 90f2a945a44d 32 seconds ago 300.6MBdocker.io/centos latest 328edcd84f1b 11 days ago 192.5MBlong long 328edcd84f1b 11 days ago 192.5MB (2)基于本地模板导入模块获取,可以直接在网上下载一个模块[root@izwz920g719hydx1spem46z ~]# wget https://download.openvz.org/template/precreated/contrib/centos-7-x86_64-minimal-20170709.tar.xz http://openvz.org/Download/templates/precreated 可惜速度并不快,若我们下载了一个centos的模板 centos-7-x86_64-minimal-20170709.tar.xz那么导入该镜像的命令为:cat centos-7-x86_64-minimal-20170709.tar.xz |docker import - centos-5-x862.3.6、存出和载入镜像以及上传镜像docker save -o ***.tar IMAGE:TAGdocker load --input ***.tar 或 dokcer load < ***.tardocker push IMAGE_NAME把现有镜像,导出为一个文件,可以作为备份:docker save -o long.tar long:long 我们还可以用该文件恢复本地镜像:docker load --input long.tar 或者docker load < long.tar docker push image_name //可以把自己的镜像传到dockerhub官方网站上去,但前提是需要先注册一个用户,后续如果有需求再研究吧三、操作Docker容器3.1、创建容器当使用docker run来创建并启动容器时,Docker在后台运行的标准操作:(1)检查本地是否存在指定的镜像centos,不存在就从公有仓库下载(2)利用镜像创建并启动一个容器(3)分配一个文件系统,并在只读的镜像层外面挂载一层可读写层(4)从宿主主机配置的桥接网络接口中桥接一个虚拟接口到容器中去(5)从地址池配置一个IP地址给容器(6)执行用户指定的应用程序(7)执行完毕后,容器被终止语法:创建容器:docker create -it {image_name}docker create命令新建的容器处于停止状态,可以使用docker start命令来启动它。 启动容器:docker start {container_id} 新建并启动容器:docker run -t -i centos /bin/bash用下载到的镜像开启容器,-i表示让容器的标准输入打开,-t表示分配一个伪终端,要把-i -t 放到镜像名字前面[root@localhost ~]# docker run -t -i nginx /bin/bashroot@c1eff06c8501:/# 守护态运行容器:docker run -itd centos /bin/bash3.2、终止容器可以使用docker stop来终止一个运行中的容器,改命令的格式为docker stoop [container]首先向容器发送SIGTERM信号,等待一段超时时间(默认为10s)后,再发送SIGKILL信号来终止容器docker kill命令会直接发送SIGKILL信号来强行终止容器[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES402e1bd8ff16 centos "/bin/bash" 16 hours ago Up 16 hours mynginx[root@localhost ~]# docker stop mynginxmynginx3.3、进入容器进入容器有以下3种方法:(1)attach命令(2)exec命令(推荐方式)(3)nsenter工具(1)attach命令[root@localhost ~]# docker attach mynginx[root@402e1bd8ff16 /]#注意:使用attach命令有时候并不方便,当多个窗口同时使用attach命令链接到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法进行操作。(2)exec命令(推荐方式)[root@localhost ~]# docker exec -it mynginx /bin/bash[root@402e1bd8ff16 /]#(3)nsenter工具[root@localhost ~]# yum install -y util-linux #安装nsenter工具为了使nsenter链接到容器,还需要找到容器进程的PID,可以通过以下命令获取PID=$(docker inspect --format "{{.State.Pid}}"
处理方法:更改配置文件:/etc/docker/daemon.json [root@localhost ~]# vim /etc/docker/daemon.json{"insecure-registries":["192.168.0.134:5000"]}修改完配置文件需要进行重启docker[root@localhost ~]# systemctl restart docker docker重启后,原先运行的容器会停止掉,需要重新开启容器[root@localhost ~]# docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry[root@localhost ~]# docker push 192.168.0.134:5000/test2The push refers to a repository [192.168.0.134:5000/test2]c4c704007df5: Pushedlatest: digest: sha256:2fa255d11989458a1f9d3173e36a911c5f40c0ba1d74b16608a27ba52fa9237a size: 528[root@localhost ~]# curl http://192.168.0.134:5000/v2/_catalog{"repositories":["test2"]} 在第二台机器(192.168.0.136)上进行验证私有仓库是否可用[root@backup ~]# yum install -y docker[root@backup ~]# systemctl start docker[root@backup ~]# curl http://192.168.0.134:5000/v2/_catalog{"repositories":["test2"]}[root@backup ~]# docker pull 192.168.0.134:5000/test2Using default tag: latestTrying to pull repository 192.168.0.134:5000/test2 ...Get https://192.168.0.165:5000/v1/_ping: http: server gave HTTP response to HTTPS client出现在docker私有仓库一样的错误,于是同样修改配置文件[root@backup ~]# vim /etc/docker/daemon.json{"insecure-registries":["192.168.0.134:5000"]}[root@backup ~]# systemctl restart docker[root@backup ~]# docker pull 192.168.0.134:5000/test2Using default tag: latestTrying to pull repository 192.168.0.134:5000/test2 ...latest: Pulling from 192.168.0.134:5000/test29ff86f02c57e: Pull completeDigest: sha256:2fa255d11989458a1f9d3173e36a911c5f40c0ba1d74b16608a27ba52fa9237a[root@backup ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZE192.168.0.165:5000/test2 latest def358072817 Less than a second ago 106.7 MB小结:仓库概念的引入,为Docker镜像文件的分发和管理提供了便捷的途径,在企业生产环境中,则往往需要使用私有仓库来维护内部镜像。 五、Docker数据管理用户在使用Docker的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据共享,这必然涉及到容器的数据管理操作。容器中管理数据主要有两种方式:(1)数据卷(Data Volumes)(2)数据卷容器(Data Volumes Dontainers) 5.1、数据卷数据卷可以是一个可供容器使用的特殊目录。a.数据卷可以在容器中共享和重用b.对数据卷修改会立马生效c.对数据卷更新,不会影响镜像d.卷会一直存在,直到没有容器使用数据卷的使用,类似于Linux下对目录或文件进行mount操作在容器内创建一个数据卷在使用docker run命令的时候,使用-v标记可以在容器内创建一个数据卷,多次使用-v标记,可以创建多个数据卷。使用-v标记也可以指定本地的已有的目录到容器中作为数据卷。也就是映射宿主机目录到容器中去。这个功能在测试的时候十分方便,比如用户可以放置一些程序或数据到本地目录,然后再容器中运行和使用。另外,本地目录的路径必须是绝对路径,如果目录不存在,Docker会自行创建。Docker挂载数据卷的默认权限是rw,用户也可以通过指定权限,ro指定可读:docker run -itd -P --name web2 -v /data:/data:ro centos_nginx:1.10 bash同时,也可以挂载本地主机的一个文件作为数据卷docker run -it --rm -P --name web2 -v ~/.bash_history:/.bash_history centos_nginx:1.10 bash 5.2、挂载本地的目录到容器里(1)查看本地镜像[root@localhost ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEcentos_nginx 1.10 3cdab9e3fdbb 19 hours ago 361.6 MBcentos_nginx latest 3cdab9e3fdbb 19 hours ago 361.6 MB(2)创建容器,并将本地/data目录映射到容器中[root@localhost ~]# docker run -itd -P --name web2 -v /data:/data centos_nginx:1.10 bash52babe20009cb2366ebe0a9e3633140bcaa2d92e2057c56e47b8377960f43d62//-v 用来指定挂载目录,:前面的/data/为宿主机本地目录,:后面的/data/为容器里的目录,会在容器中自动创建[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES52babe20009c centos_nginx:1.10 "bash" 3 seconds ago Up 3 seconds 0.0.0.0:32771->80/tcp web2(3)在数据卷目录中创建目录123[root@localhost ~]# docker exec -it 52babe20009c bash[root@52babe20009c /]# mkdir /data/123[root@52babe20009c /]# ll /data/total 24drwxr-xr-x 2 root root 4096 Nov 12 07:06 123drwxr-xr-x 5 1003 1003 4096 Sep 30 03:17 logsdrwxr-xr-x 8 1003 1003 4096 Oct 19 04:16 mysqldrwxr-xr-x 3 1003 1003 4096 Sep 30 03:18 nginxdrwxr-xr-x 2 1003 1003 4096 Oct 1 13:01 oldboydrwxr-xr-x 2 1003 1003 4096 Sep 30 03:17 web(4)宿主机查看目录变化[root@localhost ~]# ll /data/total 24drwxr-xr-x 2 root root 4096 Nov 12 02:06 123drwxr-xr-x 5 mysql mysql 4096 Sep 29 23:17 logsdrwxr-xr-x 8 mysql mysql 4096 Oct 19 00:16 mysqldrwxr-xr-x 3 mysql mysql 4096 Sep 29 23:18 nginxdrwxr-xr-x 2 mysql mysql 4096 Oct 1 09:01 oldboydrwxr-xr-x 2 mysql mysql 4096 Sep 29 23:17 web5.3、数据卷容器如果用户需要在容器之间共享一些持续更新的数据,最简单的方式是试用数据卷容器。数据卷容器其实就是一个普通的容器,专门用它来提供数据卷供其他容器挂载使用。(1)首先创建一个数据卷容器dbdata,并在其中创建一个数据卷挂载到/dbdata[root@localhost ~]# docker run -it -v /dbdata --name dbdata centostips:这里的/dbdata是容器里的/dbdata目录,并非宿主机本地的目录(2)查看/dbdata目录,并创建文件[root@8ee4460dccae /]# lsanaconda-post.log bin dbdata dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var[root@8ee4460dccae /]# touch /dbdata/long.txt[root@8ee4460dccae /]# ll /dbdata/total 0-rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt[root@8ee4460dccae /]# exit(3)通过--volumes-from来挂载dbdata容器中的数据卷,例如创建一个db1容器,并从dbdata容器挂载数据卷[root@localhost ~]# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES8ee4460dccae centos "/bin/bash" 2 minutes ago Exited (0) About a minute ago dbdata[root@localhost ~]# docker run -it --volumes-from dbdata --name db1 centos bash(4)查看db1容器是否存在/dbdata目录,并在该目录下创建long2.txt文件[root@ee0f12d8023b /]# ll /dbdata/total 0-rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt[root@ee0f12d8023b /]# touch /dbdata/long2.txt[root@ee0f12d8023b /]# exit (5)进入dbdata容器查看是否有long2.txt[root@localhost ~]# docker exec -it 8ee4460dccae bash[root@8ee4460dccae /]# ll /dbdata/total 0-rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt-rw-r--r-- 1 root root 0 Nov 12 07:15 long2.txt(6)多次使用--volumes-from参数来从多个容器挂载多个数据卷[root@localhost ~]# docker run -itd --name db5 --volumes-from db1 --volumes-from db4 centos bash9513d4c30a85601b8d0939e4b58e24697df6417fb0b82a5eb5dfc42ed729cc7b[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES9513d4c30a85 centos "bash" 5 seconds ago Up 3 seconds db572ae1898a04d centos "bash" 56 seconds ago Up 55 seconds db4ee0f12d8023b centos "/bin/bash" 51 minutes ago Up 50 minutes db1[root@localhost ~]# docker exec -it db5 bash[root@9513d4c30a85 /]# lsanaconda-post.log bin dbdata dbdata4 dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var (7)还可以从其他已经挂载了容器卷的容器来挂载容器卷: [root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESee0f12d8023b centos "/bin/bash" 47 minutes ago Up 46 minutes db18ee4460dccae centos "/bin/bash" 49 minutes ago Up 45 minutes dbdata[root@localhost ~]# docker run -it --name db2 --volumes-from db1 centos bash[root@701a34da1cde /]# ll /dbdata/total 0-rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt-rw-r--r-- 1 root root 0 Nov 12 07:15 long2.txttips:使用--volumes-from参数所挂载数据卷的容器自身并不需要保持在运行状态,如果删除了挂载的容器(包括dbdata,db1,db2),数据卷并不会被自动删除,如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显示使用docker rm -v 命令来指定删除关联的容器(1)停止db4容器并删除[root@localhost ~]# docker stop db4db4[root@localhost ~]# docker rm db4db4(2)进入db5容器查看数据卷dbdata4是否存在[root@localhost ~]# docker exec -it db5 bash[root@9513d4c30a85 /]# lsanaconda-post.log bin dbdata dbdata4 dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var 5.4、利用数据卷容器迁移数据可以利用数据卷容器对其中的数据卷进行备份,恢复,以实现数据的迁移。(1)备份[root@localhost ~]# docker run --volumes-from dbdata -v /backup:/backup --name work centos tar cvf /backup/backup.tar /dbdatatar: Removing leading `/' from member names/dbdata//dbdata/long.txt/dbdata/long2.txt[root@localhost ~]# ll /backup/-rw-r--r-- 1 root root 10240 Nov 12 03:30 backup.tar 说明:首先利用centos镜像创建了一个容器work,使用--volumes-from dbdata参数来让容器挂载dbdata容器的数据卷(即dbdata数据卷);-v /backup:/backup参数来将本地的备份目录(/backup)挂载到work容器的/backup目录。work容器启动后,使用了tar cvf /backup/backup.tar /dbdata命令来将/dbdata下的内容备份为容器内的/backup/backup.tar,即宿主机/backup目录下的/backup/backup.tar (2)恢复[root@localhost ~]# docker run -itd -v /dbdata --name db6 centos bashbb0357aba6fcee546eda5903f40cf61b3fd46a4ad9e0962e55550caaea10e06c[root@localhost ~]# docker run --volumes-from db6 -v /backup:/backup --name db7 centos tar xvf /backup/backup.tardbdata/dbdata/long.txtdbdata/long2.txt[root@localhost ~]# docker exec -it db6 bash[root@bb0357aba6fc /]# ll /dbdata/total 0-rw-r--r-- 1 root root 0 Nov 12 07:12 long.txt-rw-r--r-- 1 root root 0 Nov 12 07:15 long2.txt说明:首先利用centos镜像新建一个db6的容器,然后通过--volumes-from参数挂载db6容器的数据卷(/dbdata)新建容器,并将本地的/backup目录映射到db7容器中。而后对/backup/backup.tar进行解压到/dbdata目录下,从而实现db6恢复/dbdata数据小结:在生产环境中,在使用数据卷或者数据卷容器之外,定期将宿主机的本地数据进行备份,或者使用支持容错的存储系统,包括RAID或分布式文件系统。 六、端口映射和容器互联6.1、端口映射,实现外部访问在启动容器的时候,如果不指定对应的参数,在容器外部是无法通过网络进行访问容器内的应用和服务的。当容器中运行一些网络应用,要让外部访问这些应用,可以通过-P或-p参数来指定端口映射。当使用-P标记时,Docker会随机映射一个49000~49900的端口至容器内部开放的网络端口。端口映射的方式:(1)映射所有接口地址使用hostPort:containerPort格式,将本地的5000端口映射到容器的5000端口,可以执行以下命令:docker run -d -p 5000:5000 centos_nginx bash此时默认会绑定本地所有接口上的所有地址。多次使用-p标记可以绑定多个端口。例如:docker run -d -p 5000:5000 -p 8082:80 centos_nginx bash(2)映射到指定地址的指定端口可以使用ip:hostPort:containerPort格式指定映射一个特定的地址,例如localhost的地址127.0.0.1docker run -d -p 127.0.0.1:5000:5000 centos_nginx bash(3)映射到指定地址的任意端口使用ip::containerPort绑定localhost的任意端口到容器的5000端口,本地主机会任意分配一个端口docker run -d -p 127.0.1.1::5000 centos_nginx bash(4)查看端口映射情况docker port container_name/container_id演示:(1)以centos_nginx镜像启动一个容器(web_nginx),并将宿主机8081端口进行映射[root@localhost ~]# docker run -itd --name web_nginx -p 8081:80 centos_nginx bashc558c2a986929f280e7b1db2c46c5951fa95670dfa54de1df83f8b0335241c3c[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESc558c2a98692 centos_nginx "bash" 6 seconds ago Up 4 seconds 0.0.0.0:8081->80/tcp web_nginx(2)进入容器,启动nginx,发现Operation not permitted报错[root@localhost ~]# docker exec -it web_nginx bash[root@c558c2a98692 /]# ps -ef |grep nginxroot 26 13 0 05:59 ? 00:00:00 grep --color=auto nginx[root@c558c2a98692 /]# systemctl start nginxFailed to get D-Bus connection: Operation not permitted解决:•新建的容器,启动nginx或者httpd服务的时候会报错•Failed to get D-Bus connection: Operation not permitted• 这是因为dbus-daemon没有启动,解决该问题可以这样做• 启动容器时,要加上--privileged -e "container=docker",并且最后面的命令改为/usr/sbin/initdocker run -itd --privileged -e "container=docker" centos_with_nginx /usr/sbin/init但是如果直接使用nginx命令直接启动,nginx也是可以的。(3)删除容器,使用参数--privileged -e "container=docker",bash改为/usr/sbin/init重新启动一个容器,并查看端口映射[root@localhost ~]# docker rm -f web_nginxweb_nginx[root@localhost ~]# docker run -itd --privileged -e "container=docker" --name web_nginx -p 8081:80 centos_nginx /usr/sbin/initc57f0ef025b8b61ced5b39d6cf088f6258b536eecbe05868cb8adadf3610db44[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESc57f0ef025b8 centos_nginx "/usr/sbin/init" 7 seconds ago Up 6 seconds 0.0.0.0:8081->80/tcp web_nginx(4)启动nginx,并写入网页内容,查看是否实现端口映射[root@localhost ~]# docker exec -it web_nginx bash[root@c57f0ef025b8 /]# ps -ef |grep nginxroot 75 63 0 06:03 ? 00:00:00 grep --color=auto nginx[root@c57f0ef025b8 /]# systemctl start nginx[root@c57f0ef025b8 /]# ps -ef |grep nginxroot 82 1 0 06:03 ? 00:00:00 nginx: master process /usr/sbin/nginxnginx 83 82 0 06:03 ? 00:00:00 nginx: worker processroot 85 63 0 06:03 ? 00:00:00 grep --color=auto nginx[root@c57f0ef025b8 /]# cp /usr/share/nginx/html/index.html{,.bak}[root@c57f0ef025b8 /]# echo "www.deng.com
" > /usr/share/nginx/html/index.html6.2、互联机制实现容器间便捷互访容器的互联(linking)是一种可以让多个容器中应用进行快速交互的方式。它会在源和接收容器之间创建连接关系,接受容器可以通过容器名快速访问到源容器,而不用指定具体的IP地址。 七、使用Dokcerfile创建镜像7.1、Dockerfile基本结构Dockerfile是为了快速构建镜像Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。一般而言,Dockerfile分为4个部分:基础镜像信息
维护者信息
镜像操作指令
容器启动时执行指令示例:#This dockerfile uses the centos image#VERSION 1#Author:docker_user#Command format:Instruction [arguments / command] .. #第一行必须制定基于的基础镜像FROM centos#维护者信息MAINTAINER docker_user docker_user@email.com#镜像的操作指令RUN echo "hello world"RUN yum update && yum install -y net-toolsRUN yum install -y nginx#容器启动时执行指令CMD /usr/sbin/nginx其中,一开始必须指明所基于的镜像名称,接下来一般会说明维护者信息。后面则是镜像操作指令,例如RUN指令,RUN指令将对镜像执行跟随的命令。每运行一条RUN指令,镜像添加新的一层,并提交。最后是CMD指令,来指定运行容器时操作的命令。 7.2、Dockerfile指令指令的一般格式为INSTRUCTION arguments(1)FROM指定所创建镜像的基础镜像,如果本地不存在,则默认会去Docker Hub下载指定镜像。格式:FROM 或 FROM
:
•CMD command param1 param2
•CMD ["param1", "param2"]RUN和CMD看起来很像,但是CMD用来指定容器启动时用到的命令,只能有一条。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时,指定了运行命令,则会覆盖掉CMD指定的命令。比如:CMD ["/bin/bash", "/usr/local/nginx/sbin/nginx", "-c", "/usr/local/nginx/conf/nginx.conf"] (5)EXPOSE声明镜像内服务所监听的端口格式:EXPOSE
ENTRYPOINT command param1 param2 (shell中执行)此时,CMD指令指定值将作为根命令的参数配置容器启动后执行的命令,并且不可被docker run 提供的参数覆盖,每个Dockerfile中只能有一个ENTRYPOINT,当指定多个ENTRYPOINT时,只有最后一个生效。在运行时,可以被--entrypoint参数覆盖掉,如docker run --entrypoint•我们在Dockerfile中指定如下CMD:• CMD ["/bin/echo", "test"]• 启动容器的命令是 docker run aming这样会输出test• 假如启动容器的命令是 docker run -it aming /bin/bash 什么都不会输出• ENTRYPOINT不会被覆盖,而且会比CMD或者docker run指定的命令要靠前执行• ENTRYPOINT ["echo", "test"]• docker run -it aming 123• 则会输出 test 123,这相当于要执行命令 echo test 123 (10)VOLUME创建一个数据卷挂载点格式:VOLUME ["/data"]创建一个可以从本地主机或其他容器挂载的挂载点,一般用于存放数据库和需要保持的数据等。 (11)USER格式:USER daemon指定运行容器时的用户名或UID,后续的RUN也会指定用户。当服务不需要管理员权限时,可以通过该指令指定运行的用户。并且可以在之前创建所需要的用户。例如:RUN groupadd -r postgres && useradd -r -g postgres postgres。要临时获取管理员权限可以使用gosu,而不推荐sudo (12)WORKDIR格式:WORKDIR /path/to/workdir为后续的RUN,CMD,ENTRYPOINT指令配置工作目录。可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd则最终路径为:/a/b/c (13)ARG指定一些镜像内使用的参数(例如版本号信息等),这些参数在执行docker build命令时,才以--build-arg
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...] 如果基于image-A创建新的镜像时,新的Dockerfile中使用FROM image-A指定基础镜像,会自动执行ONBUILD指令的内容 (15)STOPSIGNAL指定所创建镜像启动的容器接收退出的信号值。例如:STOPSIGNAL signal (16)HEALTHCHECK配置所启动容器如何进行健康检查(如何判断健康与否),自docker 1.12开始支持格式有两种:HEALTHCHECK [OPTIONS] CMD command:根据所执行命令返回值是否为0来判断;HEALTHCHECK NONE:禁止基础镜像中的健康检查。OPTION支持:①--interval=DURATION(默认为:30s):过多久检查一次;②--timeout=DURATION(默认为:30s):每次检查等待结果的超时;③--retries=N(默认为:3):如果失败了,重试几次才最终确定失败。 (17)SHELL指定其他命令使用shell时的默认shell类型SHELL ["executable","parameters"]默认值为["/bin/sh","-c"] 7.3、创建镜像编写完Dockerfile之后,可以通过docker build命令来创建镜像。格式:docker build [选项] 内容路径该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下的所有内容发送给Docker服务端,有服务端来创建镜像。因此除非生成镜像需要,否则一般建议放置Dockerfile的目录为空目录,可以使用-f选项来指定其路径。①如果使用非内容路径下的Dockerfile,可以通过-f选项来指定其路径②要指定生成镜像的标签信息,可以使用-t选项例如:指定的Dockerfile所在路径为/tmp/docker_builder/,并且希望生成的镜像标签为build_repo/frist_image,可以使用:docker build -t build_repo/first_image /tmp/docker_builder/ 7.4、Dockerfile创建镜像示例(nginx)(1)编辑Dockerfile文件[root@localhost ~]# vim DockerfileFROM centosMAINTAINER long 442305405@qq.comRUN yum install -y pcre-devel wget net-tools gcc zlib zlib-devel make openssl-develADD http://nginx.org/download/nginx-1.12.2.tar.gz .RUN tar zxvf nginx-1.12.2.tar.gzRUN mkdir -p /usr/local/nginxRUN cd nginx-1.12.2 && ./configure --prefix=/usr/local/nginx && make && make installRUN rm -fv /usr/local/nginx/conf/nginx.confADD http://www.apelearn.com/study_v2/.nginx_conf /usr/local/nginx/conf/nginx.confADD index.html /usr/local/nginx/html/index.htmlRUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.confEXPOSE 80ENTRYPOINT /usr/local/nginx/sbin/nginx(2)创建镜像[root@localhost ~]# docker build -t centos_nginx:1.12.2 .Sending build context to Docker daemon 212.7 MBStep 1 : FROM centos ---> d123f4e55e12Step 2 : MAINTAINER long 442305405@qq.com ---> Using cache ---> 42a2766d5cceStep 3 : RUN yum install -y pcre-devel wget net-tools gcc zlib zlib-devel make openssl-devel ---> Running in ebd2bc43b045Loaded plugins: fastestmirror, ovl...... Step 8 : RUN rm -fv /usr/local/nginx/conf/nginx.conf ---> Running in eb41c1c7b39dremoved '/usr/local/nginx/conf/nginx.conf' ---> d6b0d765ca2eRemoving intermediate container eb41c1c7b39dStep 9 : ADD http://www.apelearn.com/study_v2/.nginx_conf /usr/local/nginx/conf/nginx.confDownloading [==================================================>] 1.678 kB/1.678 kB ---> efffda0c218dRemoving intermediate container af06898e74f4Step 10 : EXPOSE 80 ---> Running in fb3905caf714 ---> 6efacb9d8a12Removing intermediate container fb3905caf714Step 11 : ENTRYPOINT /usr/local/nginx/sbin/nginx && tail -f /etc/passwd ---> Running in 61b617e30d2b ---> 02447e813325Removing intermediate container 61b617e30d2bSuccessfully built 02447e813325(3)查看创建的镜像,并通过创建的镜像创建容器[root@localhost ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEcentos_nginx 1.12.2 02447e813325 About a minute ago 350 MB[root@localhost ~]# docker run -itd centos_nginx:1.12.2 bash10fa28dc417e0023004f857f72537e232a63b2977fda3228a77688d33b0d7803[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES10fa28dc417e centos_nginx:1.12.2 "/bin/sh -c '/usr/loc" 3 seconds ago Up 3 seconds 80/tcp gigantic_agnesi(4)进入容器查看nginx运行状况[root@localhost ~]# docker exec -it gigantic_agnesi bash[root@10fa28dc417e /]# ps -ef |grep nginxroot 1 0 0 06:37 ? 00:00:00 /bin/sh -c /usr/local/nginx/sbin/nginxroot 6 1 0 06:37 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginxnobody 7 6 0 06:37 ? 00:00:00 nginx: worker processnobody 8 6 0 06:37 ? 00:00:00 nginx: worker processroot 24 10 0 06:38 ? 00:00:00 grep --color=auto nginx 7.5.遇到的问题由于之前使用过pipework进行配置桥接网络,需要更改网络,并开启IPv4转发[root@localhost ~]# docker run -itd --name test centos_nginx bashWARNING IPv4 forwarding is disabled. Networking will not worka93d14f536d31b3edfd847f12c8e1115bb75bc2b202fb44f761c2e14c2018a6b解决:# vi /etc/sysctl.conf或者# vi /usr/lib/sysctl.d/00-system.conf添加如下代码: net.ipv4.ip_forward=1重启network服务# systemctl restart network查看是否修改成功# sysctl net.ipv4.ip_forward 来源:https://blog.51cto.com/jinlong/2104972