0


【Docker篇】Dockerfile构建过程,Dockerfile指令,CMD 和 ENTRYPOINT 的区别

文章目录

Dockerfile

在前面的文章中我们就说过,镜像可以打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。我们在使用过程中通常会直接拉取官方为我们制作好的镜像,那么我们能不能自己制作镜像呢?

答案是肯定的。使用到的就是Dockerfile。

1. 什么是Dockerfile

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

Dockerfile中记录了镜像制作过程中的每一个详细的步骤,我们到官网上看看一个centos的镜像是怎么做出来的。

https://hub.docker.com/_/centos

在这里插入图片描述
在这里插入图片描述

这是官网上centos镜像的Dockerfile,可以看到一个centos镜像里面都包含了哪些内容。

我们也可以仿照此制作自己的镜像。

构建镜像一般有以下几个步骤:

  1. 编写Dockerfile文件
  2. docker build 构建镜像
  3. docker run 运行

2. Dockerfile构建过程

基础知识

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. 表示注释

  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交

流程

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器做出修改
  3. 执行类似 docker commit 的操作提交一个新的镜像层
  4. Docker再基于刚提交的镜像运行一个新容器
  5. 执行Dockerfile中的下一条指令直到所有指令都执行完成!

说明
从应用软件的角度来看,Dockerfile,docker镜像与docker容器分别代表软件的三个不同阶段。

  • Dockerfile 是软件的原材料 (代码)
  • Docker 镜像则是软件的交付品 (.apk)
  • Docker 容器则是软件的运行状态 (客户下载安装执)

Dockerfile 面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可!

在这里插入图片描述

Dockerfile:需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。

Docker镜像:在Dockerfile 定义了一个文件之后,Docker build 时会产生一个Docker镜像,当运行Docker 镜像时,会真正开始提供服务;

Docker容器:容器对外提供服务。
在这里插入图片描述

3. Dockerfile指令

关键字

上面我们看了制作centos镜像的Dockerfile,里面就是一些指令,我们这里将一些常用指令进行汇总。

FROM         # 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER  # 镜像维护者的姓名和邮箱地址
RUN         # 容器构建时需要运行的命令
EXPOSE        # 当前容器对外保留出的端口
WORKDIR     # 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点
ENV         # 用来在构建镜像过程中设置环境变量
ADD         # 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY         # 类似ADD,拷贝文件和目录到镜像中!
VOLUME         # 容器数据卷,用于数据保存和持久化工作
CMD         # 指定一个容器启动时要运行的命令,Dockerfile中可以有多个CMD指令,但只有最后一个生效!
ENTRYPOINT     # 指定一个容器启动时要运行的命令!和CMD一样
ONBUILD     # 当构建一个被继承的Dockerfile时运行命令,父镜像在被子镜像继承后,父镜像的ONBUILD被触发

这里注意ADD和COPY的区别,经常使用

看指令不太好理解,我们通过一张图片来给大家说明。

在这里插入图片描述

4. 实战测试

4.1 制作centos镜像

我们从centos的Dockerfile中可以看出,centos镜像来源于一个base镜像(Scratch),Docker Hub中绝大多数镜像都是通过此基础镜像安装和配置需要的软件构建。

在这里插入图片描述

当我们使用官网提供的centos时会发现很多问题,比如没有

vim

命令编辑器,查看网络配置ifconfig等等,我们现在做一个镜像,能够使用这些命令。

在这里插入图片描述

  1. 编写Dockerfile
[root@jiangnan centos]# pwd
/home/centos
[root@jiangnan centos]# vim Dockerfile-centos [root@jiangnan centos]# cat Dockerfile-centos 
FROM centos:7
MAINTAINER jiangnan<[email protected]>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum install -y vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo$MYPATH
CMD echo"----------end--------"
CMD /bin/bash
[root@jiangnan centos]# 

说明:我们这里以centos7为基础镜像。

  1. 构建
docker build -f /home/centos/Dockerfile-centos -t mycentos:1.0 .

-f:指定Dockerfile文件。-t:给镜像命名。后面有个点不要忘了。

[root@jiangnan centos]# docker build -f /home/centos/Dockerfile-centos -t mycentos:1.0 .
Sending build context to Docker daemon  2.048kB
Step 1/10 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/10 : MAINTAINER jiangnan<[email protected]>
 ---> Running in 6fd0d509a785
Removing intermediate container 6fd0d509a785
 ---> 9945ff2fb154
Step 3/10 : ENV MYPATH /usr/local
........
 ---> a4b55ee0c621
Successfully built a4b55ee0c621
Successfully tagged mycentos:1.0
[root@jiangnan centos]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
mycentos     1.0       a4b55ee0c621   About a minute ago   570MB
centos       7         eeb6ee3f44bd   5 months ago         204MB
[root@jiangnan centos]# 

注意:构建命令最后有个

.
  1. 运行
[root@jiangnan centos]# docker run -it mycentos:1.0 /bin/bash[root@669ce95e0e0b local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0(Ethernet)
        RX packets 7  bytes 586(586.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0(0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000(Local Loopback)
        RX packets 0  bytes 0(0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0(0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0[root@669ce95e0e0b local]# vim hello.txt[root@669ce95e0e0b local]# cat hello.txt 
hello,Docker
[root@669ce95e0e0b local]# 

可以看到我们要的效果达到了。

  1. 查看历史变更步骤

我们前面也说了,Dockerfile中记录了镜像制作过程中的每一个详细的步骤,那我们怎么看呢?

docker history 镜像名ID
[root@jiangnan centos]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED             SIZE
mycentos     1.0       a4b55ee0c621   About an hour ago   570MB
centos       7         eeb6ee3f44bd   5 months ago        204MB
[root@jiangnan centos]# docker history a4b55ee0c621
IMAGE          CREATED             CREATED BY                                      SIZE      COMMENT
a4b55ee0c621   About an hour ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B        
c7d422106fd9   About an hour ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B        
07b9b6147049   About an hour ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B        
20704538d7c4   About an hour ago   /bin/sh -c #(nop)  EXPOSE 80                    0B        
9c58a0593f09   About an hour ago   /bin/sh -c yum -y install net-tools             156MB     
341ac0e40b31   About an hour ago   /bin/sh -c yum install -y vim                   211MB     
52a117dd18a2   About an hour ago   /bin/sh -c #(nop) WORKDIR /usr/local            0B        
746a15b8b0fa   About an hour ago   /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B        
9945ff2fb154   About an hour ago   /bin/sh -c #(nop)  MAINTAINER jiangnan<xxc11…   0B        
eeb6ee3f44bd   5 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        <missing>5 months ago        /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        <missing>5 months ago        /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB     [root@jiangnan centos]# 

说明:从这里可以看出我们在Dockerfile中定义每一个步骤都会有记录。而且我们还发现了一个很重要的规律,Dockerfile是由上往下写的,但是镜像是从下往上的,这就验证了我们之前说的镜像是一层一层叠加起来的

4.2 制作tomcat镜像

我们知道tomcat镜像运行需要jdk环境,那么这次我们将jdk连同tomcat一同打包成镜像。

首先准备好jdk和tomcat安装包
在这里插入图片描述

  1. 编写Dockerfile
# 设置基础镜像
FROM centos:7
# 设置作者
MAINTAINER jiangnan<[email protected]># 将readme.txt复制到容器中
COPY readme.txt /usr/local
# 将安装包复制到容器中并配置环境变量
ADD jdk-8u161-linux-x64.tar.gz /usr/local
ENV JAVA_HOME /usr/local/jdk1.8.0_161
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

ADD apache-tomcat-9.0.58.tar.gz /usr/local
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.58
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.58
ENV PATH$PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
# 删除不需要的安装包
RUN rm -f /usr/local/*.tar.gz
# 设置工作目录
WORKDIR /usr/local/apache-tomcat-9.0.58
# 暴露端口
EXPOSE 8080# 启动tomcat
ENTRYPOINT ["./bin/catalina.sh", "run"]
  1. 构建镜像
[root@jiangnan tomcat]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
mytomcat     1.0       2733bd702ea7   8 seconds ago   604MB
centos       7         eeb6ee3f44bd   5 months ago    204MB
[root@jiangnan tomcat]# 
  1. 运行
[root@jiangnan tomcat]# docker run -dit --name=divtomcat -p 9090:8080 -v /home/tomcat/webapps/:/usr/local/apache-tomcat-9.0.58/webapps mytomcat:1.0
962898ed75522850347bca325ff213f6ce869d2d6a762c0710e61ca8b86ff6da
[root@jiangnan tomcat]# 
  1. 将我们的项目cp到webapps目录下
[root@jiangnan tomcat]# cp -rf music webapps/[root@jiangnan tomcat]# cd webapps/music/[root@jiangnan music]# ll
total 24
drwxr-xr-x 2 root root 4096 Feb 2619:15 css
drwxr-xr-x 2 root root 4096 Feb 2619:15 images
-rw-r--r-- 1 root root 2707 Feb 2619:15 index.html
drwxr-xr-x 2 root root 4096 Feb 2619:15 js
[root@jiangnan music]# 

/home/tomcat/webapps/和/usr/local/apache-tomcat-9.0.58/webapps进行了挂载。

  1. 外网进行访问

在这里插入图片描述

4.3 CMD 和 ENTRYPOINT 的区别

我们之前说过,两个命令都是指定一个容器启动时要运行的命令。

CMD:Dockerfile 中可以有多个CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换!
ENTRYPOINT: docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合!

测试:

CMD

  1. 新建一个Dockerfile
[root@jiangnan cmd]# pwd
/home/cmd
[root@jiangnan cmd]# ll
total 4
-rw-r--r-- 1 root root 32 Feb 2614:53 Dockerfile
[root@jiangnan cmd]# cat Dockerfile 
FROM centos
CMD ["ls", "-a"][root@jiangnan cmd]# 
  1. 构建镜像
[root@jiangnan cmd]# docker build -f Dockerfile -t cmdtest .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM centos
latest: Pulling from library/centos
a1d0c7532777: Pull complete 
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest
 ---> 5d0da3dc9764
Step 2/2 : CMD ["ls", "-a"]
 ---> Running in bd1a6bba4aee
Removing intermediate container bd1a6bba4aee
 ---> 29a1a1704d9a
Successfully built 29a1a1704d9a
Successfully tagged cmdtest:latest
[root@jiangnan cmd]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
cmdtest      latest    94e05d54db92   About a minute ago   231MB
tomcat       latest    fb5657adc892   2 months ago         680MB
centos       latest    5d0da3dc9764   5 months ago         231MB
  1. 运行
[root@jiangnan cmd]# docker run 94e05d54db92...
.dockerenv
bin
dev
etc
......
usr
var
[root@jiangnan cmd]# 
  1. 参数传递

当我们运行容器,实际上执行了

ls -a

的命令,就看到了3中的效果,如果我们想执行的是

ls -al

该怎么做呢?理论上后面加上参数就可以,比如

[root@jiangnan cmd]# docker run cmd -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in$PATH: unknown.
[root@jiangnan cmd]# 

问题:我们可以看到可执行文件找不到的报错,executable file not found。
之前我们说过,跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。
因此这里的 -l 替换了原来的 CMD,而不是添加在原来的 ls -a 后面。而 -l 根本不是命令,所以自然找不到。
那么如果我们希望加入 -l 这参数,我们就必须重新完整的输入这个命令:

[root@jiangnan cmd]# docker run cmd ls -al
total 56
drwxr-xr-x   1 root root 4096 Feb 26 07:06 .
drwxr-xr-x   1 root root 4096 Feb 26 07:06 ..
-rwxr-xr-x   1 root root    0 Feb 26 07:06 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  32020 bin -> usr/bin
..........
drwxr-xr-x  12 root root 4096 Sep 1514:17 usr
drwxr-xr-x  20 root root 4096 Sep 1514:17 var
[root@jiangnan cmd]# 

ENTRYPOINT

  1. 编写Dockerfile
[root@jiangnan entrypoint]# pwd
/home/entrypoint
[root@jiangnan entrypoint]# touch Dockerfile[root@jiangnan entrypoint]# vim Dockerfile [root@jiangnan entrypoint]# cat Dockerfile 
FROM centos
ENTRYPOINT ["ls", "-a"][root@jiangnan entrypoint]# 
  1. 构建镜像
[root@jiangnan entrypoint]# docker build -f Dockerfile -t entrypoint .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls", "-a"]
 ---> Running in 07ae62691ce1
Removing intermediate container 07ae62691ce1
 ---> 7a01d22d4b6b
Successfully built 7a01d22d4b6b
Successfully tagged entrypoint:latest
[root@jiangnan entrypoint]# 
  1. 运行
[root@jiangnan entrypoint]# docker run entrypoint...
.dockerenv
bin
dev
etc
......
tmp
usr
var
[root@jiangnan entrypoint]# 
  1. 参数传递
[root@jiangnan entrypoint]# docker run entrypoint -l
total 56
drwxr-xr-x   1 root root 4096 Feb 26 07:12 .
drwxr-xr-x   1 root root 4096 Feb 26 07:12 ..
-rwxr-xr-x   1 root root    0 Feb 26 07:12 .dockerenv
.......
drwxr-xr-x  20 root root 4096 Sep 1514:17 var
[root@jiangnan entrypoint]# 

和cmd中的测试一样,我们直接跟了

-l

,但是cmd报错,而ENTRYPOINT成功了。

在这里插入图片描述

5. 发布镜像(了解)

上面的四步做完,只能算是单机版玩耍,而要实现多个环境使用,需要镜像发布。

我们这里演示将镜像发布到阿里云镜像仓库,首先要开通阿里云账号,创建命名空间和镜像仓库。

在这里插入图片描述

按照步骤做即可。

[root@jiangnan entrypoint]# docker login --username=xxxxxx registry.cn-beijing.aliyuncs.com
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@jiangnan entrypoint]# 

看到Login Succeeded说明登录成功了。

[root@jiangnan entrypoint]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
entrypoint   latest    7a01d22d4b6b   18 minutes ago   231MB
cmdtest      latest    94e05d54db92   30 minutes ago   231MB
tomcat       latest    fb5657adc892   2 months ago     680MB
centos       latest    5d0da3dc9764   5 months ago     231MB
[root@jiangnan entrypoint]# docker tag 7a01d22d4b6b registry.cn-beijing.aliyuncs.com/xxc-study/mybuild:1.0[root@jiangnan entrypoint]# docker push registry.cn-beijing.aliyuncs.com/xxc-study/mybuild:1.0
The push refers to repository [registry.cn-beijing.aliyuncs.com/xxc-study/mybuild]
74ddd0ec08fa: Pushed 
1.0: digest: sha256:29a034073345d4e389b407042b84d4a6fd2392716a80196ed1d5a44526c67d73 size: 529[root@jiangnan entrypoint]# 

在这里插入图片描述
在这里插入图片描述

6. 总结

在这里插入图片描述

  1. Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
  2. Dockerfile中记录了镜像制作过程中的每一个详细的步骤。在这里插入图片描述 我的微信公众号先已开通,各位小伙伴们可以关注我,后面文章会进行同步,方便查看哦。在这里插入图片描述
标签: docker 容器 centos

本文转载自: https://blog.csdn.net/weixin_45842494/article/details/123151006
版权归原作者 渡、️ 所有, 如有侵权,请联系我们删除。

“【Docker篇】Dockerfile构建过程,Dockerfile指令,CMD 和 ENTRYPOINT 的区别”的评论:

还没有评论