03 Docker高级实践
第三章 Docker高级实践
一、Dockerfile
在这一部分我们来介绍一些Docker的高级内容: Dockerfile和Docker compose。
1 Dockerfile简介
-
什么是Dockerfile?
类似于我们学习过的脚本,将我们在上面学到的docker镜像,使用自动化的方式实现出来。
-
Dockerfile的作用
- 找一个镜像:ubuntu
- 创建一个容器: docker run ubuntu
- 进入容器: docker exec -it 容器命令
- 操作:各种应用配置....
- 构造新镜像: docker commit
-
Dockerfile使用准则
- 大:首字母必须大写D
- 空:尽量将Dockerfile放在空目录中。
- 单:每个容器尽量只有一个功能。
- 少:执行的命令越少越好。
-
Dockerfile分为四部分
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 容器启动时执行指令
-
Dockerfile文件内容
- 首行注释信息
- 指令(大写)参数
-
Dockerfile使用命令
#构建镜像命令格式: docker build -t [镜像名]:[版本号][Dockerfile所在目录] #构建样例: docker build -t nginx:v0.2 /opt/dockerfile/nginx/ #参数详解: -t 指定构建后的镜像信息, /opt/dockerfile/nginx/ 则代表Dockerfile存放位置,如果是当前目录,则用 .(点)表示
2 Dockerfile快速入门
接下来我们快速的使用Dockerfile来基于ubuntu创建一个定制化的镜像: nginx。
- 创建文件目录
#创建Dockerfile专用目录
$ mkdir -p docker-file/dockerfile/nginx
$ cd ./docker-file/dockerfile/nginx/
#在其中创建Dockerfile文件
$ vim Dockerfile
- 在Dockerfile中书写内容:
# 构建一个基于ubuntu的docker定制镜像
# 基础镜像
FROM ubuntu
# 镜像作者
MAINTAINER yangyi yangyi@163.com
# 执行命令
RUN mkdir hello
RUN mkdir world
RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
RUN sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
RUN apt-get update
RUN apt-get install nginx -y
# 对外端口
EXPOSE 80
- 进行构建操作
#构建镜像
$ docker build -t ubuntu-nginx:v1.0 . # 依赖当前文件夹下面的Dockerfile创建文件
#查看新生成镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu-nginx v1.0 0dcd373157ad 11 minutes ago 167MB
#查看构建历史
$ docker history 0dcd373157ad
IMAGE CREATED CREATED BY SIZE COMMENT
0dcd373157ad 23 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
a4f1dd0a918d 23 minutes ago /bin/sh -c apt-get install nginx -y 59.2MB
0ffb9d0eee7b 24 minutes ago /bin/sh -c apt-get update 34.6MB
99a68a02a088 27 minutes ago /bin/sh -c sed -i 's/security.ubuntu.com/mir… 2.76kB
393d63c34bee 27 minutes ago /bin/sh -c sed -i 's/archive.ubuntu.com/mirr… 2.76kB
1cafc34dadf0 27 minutes ago /bin/sh -c mkdir world 0B
0361a0a98448 27 minutes ago /bin/sh -c mkdir hello 0B
9db7f118dcc3 27 minutes ago /bin/sh -c #(nop) MAINTAINER yangyi yangyi@… 0B
2b4cba85892a 2 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ADD file:8a50ad78a668527e9… 72.8MB
#注意:
因为容器没有启动命令,所以肯定访问不了
注:每次操作都是通过镜像生成容器,容器中进行操作之后,在生成镜像,将之前的镜像删除,如此循环往复,直到生成最终的结果。
- 运行修改好的Dockerfile进行构建
# 构建一个基于ubuntu的docker定制镜像
# 基础镜像
FROM ubuntu
# 镜像作者
MAINTAINER yangyi yangyi@163.com
# 执行命令
RUN mkdir hello && mkdir world
RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
RUN apt-get update && apt-get install nginx -y
# 对外端口
EXPOSE 80
#运行Dockerfile
$ docker build -t ubuntu-nginx:v0.2 .
#查看历史信息
$ docker history ubuntu-nginx:v0.2
#对比两个镜像的大小
$ docker images
#深度对比连个镜像的大小
$ docker inspect a853de1b8be4
$ docker inspect eaba9bd1c4ac
注:命令越少,构建的镜像越小一下。【因为有了一些日志信息😄 】
Dockerfile构建过程:
- 从基础镜像1运行一个容器A
- 遇到一条Dockerfile指令,都对容器A做一次修改操作
- 执行完毕─条命令,提交生成一个新镜像2
- 再基于新的镜像2运行一个容器B
- 遇到一条Dockerfile指令,都对容器B做一次修改操作
- 执行完毕─条命令,提交生成一个新镜像
- ...
构建过程中,创建了很多镜像,这些中间镜像,我们可以直接使用来启动容器,通过查看容器效果,从侧面能看到 我们每次构建的效果。提供了镜像调试的能力。
3 基础指令详解
-
FROM
FROM #格式: FROM <image> FROM <image>:<tag> #解释: #FROM 是 Dockerfile 里的第一条而且只能是除了首行注释之外的第一条指令 #可以有多个FROM语句,来创建多个image #FROM 后面是有效的镜像名称,如果该镜像没有在你的本地仓库,那么就会从远程仓库Pull取,如果远程也没有,就报错失败 #下面所有系统可执行指令,都在FROM的镜像中执行。
-
MAINTAINER
MAINTAINER #格式: MAINTAINER <name> #解释: #指定该dockerfile文件的维护者信息。类似我们在docker commit 时候使用-a参数指定的信息
-
RUN
RUN #格式: RUN <command> (shell模式) RUN["executable", "param1", "param2"] (exec 模式) #解释: #表示当前镜像构建时候运行的命令,如果有确认输入的话,一定要在命令中添加 -y【确认,确认软件是否安装等等】 #如果命令较长,那么可以在命令结尾使用 \ 来换行 #生产中,推荐使用上面数组的格式 #注释: #shell模式:类似于 /bin/bash -c command #举例: RUN echo hello #exec模式:类似于 RUN["/bin/bash", "-c", "command"] #举例: RUN["echo", "hello"]
-
EXPOSE
EXPOSE #格式: EXPOSE <port> [<port>...] #解释: #设置Docker容器对外暴露的端口号,Docker为了安全,不会自动对外打开端口,如果需要外部提供访问,还需要启动容器时增加-p或者-P参数对容器的端口进行分配。
4 运行时指令详解
-
CMD
CMD #格式: CMD ["executable","param1","param2"] (exec 模式)推荐 CMD command param1 param2 (shell模式) CMD ["param1","param2"] 提供给ENTRYPOINT的默认参数; #解释: #CMD指定容器启动时默认执行的命令 #每个Dockerfile只能有一条CMD命令,如果指定了多条,只有最后一条会被执行 #如果你在启动容器的时候使用docker run 指定的运行命令,那么会覆盖CMD命令。 #举例: CMD ["/usr/sbin/nginx","-g","daemon off;"] "/usr/sbin/nginx" nginx命令 "-g" 设置配置文件外的全局指令 "daemon off;" 后台守护程序开启方式 关闭 #CMD指令实践: #修改Dockerfile文件内容: #在上一个Dockerfile文件内容基础上,末尾增加下面一句话: CMD ["/usr/sbin/nginx","-g","daemon off;"] #构建镜像 $ docker build -t ubuntu-nginx:v0.3 . #根据镜像创建容器,创建时候,不添加执行命令【就会执行CMD中的】 $ docker run --name unginx-1 -itd ubuntu-nginx:v0.3 #根据镜像创建容器,创建时候,添加执行命令/bin/bash【会覆盖Dockerfile中的CMDg】 $ docker run --name unginx-2 -itd ubuntu-nginx:v0.3 /bin/bash #查看启动的容器 $ docker ps #发现两个容器的命令行是不一样的 $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a68ffd3e38b2 ubuntu-nginx:v3.0 "/bin/bash" 18 minutes ago Up 18 minutes 80/tcp unginx-2 15c04f36bd02 ubuntu-nginx:v3.0 "/usr/sbin/nginx -g …" 20 minutes ago Up 20 minutes 80/tcp unginx-1
切换到新的路径下
进行Dockerfile文件修改
构建新的镜像:
ubuntu-nginx:v3.0
使用两种方式生成容器:
-
ENTRYPOINT
ENTRYPOINT #格式: ENTRYPOINT ["executable", "param1","param2"] (exec 模式) ENTRYPOINT command param1 param2 (shell 模式) #解释: #和CMD 类似都是配置容器启动后执行的命令,并且不会被docker run提供的参数覆盖。 #每个Dockerfile 中只能有一个ENTRYPOINT,当指定多个时,只有最后一个起效。 #生产中我们可以同时使用ENTRYPOINT 和CMD, #想要在docker run 时被覆盖,可以使用"docker run --entrypoint" #ENTRYPOINT指令实践: #修改Dockerfile文件内容: #在上一个Dockerfile 文件内容基础上,修改末尾的CMD 为ENTRYPOINT: ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"] #构建镜像 $ docker build -t ubuntu-nginx:v0.4 . #根据镜像创建容器,创建时候,不添加执行命令 $ docker run --name unginx-3 -itd ubuntu-nginx:v0.4 #根据镜像创建容器,创建时候,添加执行命令/bin/bash $ docker run --name unginx-4 -itd ubuntu-nginx:v0.4 /bin/bash #查看ENTRYPOINT是否被覆盖 $ docker ps -a #根据镜像创建容器,创建时候,使用--entrypoint参数,添加执行命令/bin/bash $ docker run --entrypoint "/bin/bash" --name nginx-5 -itd ubuntu-nginx:v0.4 #查看ENTRYPOINT是否被覆盖 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6d54b6ff0209 ubuntu-nginx:v4.0 "/bin/bash" 2 minutes ago Up 2 minutes 80/tcp unginx-5
切换到新的路径下
进行Dockerfile修改
构建新的镜像:
ubuntu-nginx:v4.0
使用两种方式生成容器:
两种方式之间的区别:
如果想覆盖掉entrypoint: