layout: post
title: 构建可执行程序的Dockerfile
date: 2018-04-15
tags: [“Docker”,”自动化运维工具”]


1、RUN指令

用于指定docker build过程中运行的程序,其可以是任何命令,而且可以使用多次

Syntax

1、RUN
2、RUN [““,”“,”“]

基于第一种格式的,通常是一个shell命令,而且是由基础镜像的”/bin/sh -c”来运行它,这意味着次进程在容器中的PID不为1,不能接收UNIX信号,因此,当使用”docker stop “ 命令停止容器时,此进程接收不到SIGTERM信号(停止进程:SIGTERMSIGKILL);

基于第二种语法格式中的参数是一个JSON格式的数组,其中为要运行的命令,后面的为传递给命令的选项或参数;然而,此种格式指定的命令不会以”/bin/sh -c”来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。
RUN ["/bin/bash","-c","<executable>","<param1>"]

2、CMD指令

用于在启动容器运行容器应用的,当有多个CMD的时候,仅最后一个会生效。

Syntax:

CMD <command> #同RUN
CMD ['<executable>','<param1>','<param2>'] #同RUN
CMD ['param1','param2'] #用于ENTRYPOINT指令提供默认参数

简单示例:

  1. [root@ansible_master file_02]# vim Dockerfile
  2.  
  3. FROM busybox:latest
  4. LABEL maintainer="zhangshang"
  5. #ADD index.html /data/web/html
  6. RUN mkdir -p /data/web/html \
  7. && echo 'test RUN and CMD !' >/data/web/html/index.html
  8. EXPOSE 80/tcp
  9. CMD httpd -h /data/web/html -f

构建镜像

  1. [root@ansible_master file_02]# docker build . -t http:test1
  2. Sending build context to Docker daemon 3.072kB
  3. Step 1/5 : FROM busybox:latest
  4. ---> 8ac48589692a
  5. Step 2/5 : LABEL maintainer="zhangshang"
  6. ---> Using cache
  7. ---> 7cee9591fed5
  8. Step 3/5 : RUN mkdir -p /data/web/html && echo 'test RUN and CMD !' >/data/web/html/index.html
  9. ---> Running in e8b355a82e1d
  10. Removing intermediate container e8b355a82e1d
  11. ---> a83e40806db2
  12. Step 4/5 : EXPOSE 80/tcp
  13. ---> Running in 17d9bb504bb6
  14. Removing intermediate container 17d9bb504bb6
  15. ---> ac8ac81d7d84
  16. Step 5/5 : CMD httpd -h /data/web/html -f
  17. ---> Running in 64db8ba82a0c
  18. Removing intermediate container 64db8ba82a0c
  19. ---> 7106ff92352c
  20. Successfully built 7106ff92352c
  21. Successfully tagged http:test1

运行容器

  1. [root@ansible_master file_02]# docker run -itd --rm --name test2 http:test1
  2. 4fd41b3ab75560160dfca075d4183821c4f64334118e7d1db9aa19205058ab78
  3. [root@ansible_master file_02]# curl 172.17.0.3
  4. test RUN and CMD !

使用CMD最为默认执行程序是可以被覆盖掉的

  1. [root@ansible_master file_02]# docker run -itd --rm --name test2 http:test1 /bin/sh
  2. a863fbcc5c2f8f00476304c1cdb0493505c908657a4f4e2010701a3c19f24e26
  3. [root@ansible_master file_02]# curl 172.17.0.3
  4. curl: (7) Failed connect to 172.17.0.3:80; 拒绝连接
  5.  
  6. 以上启动的容器被/bin/sh覆盖了
3、ENTRYPOINT指令 与CMD指令相同,唯一的不同点,在运行使用ENTRYPOINT指令构建的镜像生成的容器默认执行程序不会被覆盖。所以我们一般使用ENTRYPOINT来构建镜像,只使用CMD指令来为ENTRYPOINT传递参数。所以上一个实例应该写成如下形式。
  1. [root@ansible_master file_02]# vim Dockerfile
  2.  
  3. FROM busybox:latest
  4. LABEL maintainer="zhangshang"
  5. #ADD index.html /data/web/html
  6. RUN mkdir -p /data/web/html \
  7. && echo 'test RUN and CMD !' >/data/web/html/index.html
  8. EXPOSE 80/tcp
  9. CMD ["httpd","-h","/data/web/html","-f"]
  10. ENTRYPOINT ["/bin/sh","-c"] #容器运行会直接退出,因为父进程是"sh",而httpd是子进程,父进程是在后台运行的,可以使用exec用子进程代替父进程。

或(建议都已非shell的方式运行)

  1. [root@ansible_master file_02]# vim Dockerfile
  2.  
  3. FROM busybox:latest
  4. LABEL maintainer="zhangshang"
  5. #ADD index.html /data/web/html
  6. RUN mkdir -p /data/web/html \
  7. && echo 'test RUN and CMD !' >/data/web/html/index.html
  8. EXPOSE 80/tcp
  9. CMD ["-h","/data/web/html","-f"]
  10. ENTRYPOINT ["httpd"]

CMD与ENTRYPOINT的交互方式

1)Dockerfile应至少指定CMD或ENTRYPOINT命令中的一个。
2)当使用容器作为可执行文件时,应该定义ENTRYPOINT。
3)应该使用CMD作为定义ENTRYPOINT命令的缺省参数或在容器中执行ad-hoc命令的方式。
4)使用替代参数运行容器时,CMD将被覆盖。

下表显示了针对不同的ENTRYPOINT / CMD组合执行的命令:

注意:CMD和ENTRYPOINT混用时,格式不同运行会出问题

通过脚本的方式运行ENTRYPOINT(使用ENTRYPOINT执行脚本,在运行容器时,在脚本内进行环境设定,这才是ENTRYPOINT的正确姿势)

  1. 编辑脚本
  2.  
  3. vim entrypoint.sh
  4. #! /bin/sh
  5. if ! id httpd &>/dev/null; then
  6. adduser httpd
  7. fi
  8. exec "$@"

复权

  1. chmod 755 entrypoint.sh

编辑dockerfile

  1. [root@ansible_master file_02]# vim Dockerfile
  2.  
  3. FROM busybox:latest
  4. LABEL maintainer="zhangshang"
  5. #ADD index.html /data/web/html
  6. RUN mkdir -p /data/web/html \
  7. && echo 'test RUN and CMD !' >/data/web/html/index.html
  8. EXPOSE 80/tcp
  9. CMD ["httpd","-h","/data/web/html","-f"]
  10. ENTRYPOINT ["/bin/entrypoint.sh"]
文档更新时间: 2020-03-27 13:42   作者:张尚