dockerfile详解及镜像制作

基于dockerfile制作镜像

dockerfile是什么?

Dockerfile可以说是一种可以被docker程序解释的脚本,Dockerfile是由一条条的命令组成的,每条命令对应Linux下面的一条命令,docker程序将这些Dockerfile指令再翻译成真正的Linux命令,其有自己的书写方式和支持的命令,docker程序读取Dockerfile并根据指令生成docker镜像。

结构规整

将每个不同的系统以及web镜像都创建对应的目录和dockerfile,制作基础镜像,然后是基于这些基础镜像进一步的构建生产中用的环境,就不用每次都重新去底层开始构建镜像了,直接去镜像仓库拉取就行。

[root@localhost opt]# tree dockerfile/
dockerfile/
├── system
│   ├── alpine
│   │   ├── Dockerfile
│   │   └── repositories
│   ├── centos
│   │   └── Dockerfile
│   ├── debian
│   ├── redhat
│   └── ubuntu
└── web
    ├── apache
    ├── jdk
    │   ├── Dockerfile
    │   └── jdk-8u191
    │       ├── Dockerfile
    │       └── jdk-8u191-linux-x64.tar.gz
    ├── nginx
    │   ├── alpine
    │   │   ├── Dockerfile
    │   │   ├── nginx-1.16.1.tar.gz
    │   │   └── repositories
    │   ├── centos
    │   │   ├── Dockerfile
    │   │   └── nginx-1.16.1.tar.gz
    │   └── ubuntu
    ├── php
    └── tomcat
        ├── tomcat7
        └── tomcat8
            ├── apache-tomcat-8.5.42.tar.gz
            ├── build-tomcat.sh
            ├── Dockerfile
            └── run.sh

dockerfile文件中使用命令

dockerfile官方文档:https://docs.docker.com/engine/reference/builder/
参考链接:https://blog.csdn.net/qq_41734645/article/details/105012588

FROM

FROM:基于那个镜像构建当前镜像,构建镜像时会先在本地寻找基础镜像,如果本地没有会去dockerhub或者远程仓库去下载。

LABEL,MAINTAINER

  1. 解释

LABEL:作者信息或者描述。(现在都是用这个)
MAINTAINER:作者信息或者描述。

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates that label-values can span multiple lines."

USER

USER:指定该容器运行时使用的用户名和UID(即设置构建用户),后续的RUN命令也会使用这个指定用户。生成容器之后登录进去会是user指定的用户,不是root。

USER <user>[:<group>]
USER <uid>:<gid>
USER nginx

WORKDIR

指定工作目录,和cd一样,这个指定的目录会成为容器启动后登陆进去的第一个目录。

VOLUME

  1. 解释

设置容器挂载宿主机的目录

VOLUME ["/dir_1","/dir_2",...]
VOLUME [“/data”,”/data2”]
VOLUME /data

ENV,ARG

  1. 解释
    ENV:设置镜像环境变量,在构建镜像时有效,在镜像被创建后和启动容器时环境变量依旧也有效,并且可以重写覆盖。print env可查看其值常用于向容器内传递用户密码等。
    ARG:在构建镜像时,指定一些参数,仅在build docker imag的过程中有效
例:ENV Name tiemrovers
#无默认值
ENV hey
#默认值
ENV foo /bar
#或ENV foo=/bar
#在构建过程中可以使用ENV值
ADD . $foo
#or ADD . ${foo}
#翻译为:添加。/酒吧
#使用以下docker命令设置env
docker run -e "env_var_name=another_value" alpine env
docker run -e env_var_name alpine env
docker run --env-file=env_file_name alpine env
#在Dockerfile中
ARG some_variable_name
#或硬编码默认值:
#ARG some_variable_name=默认值
RUN echo "Oh dang look at that $some_variable_name"
 
#在shell命令中
docker build --build-arg some_variable_name=a_value
#然后你会得到
Oh dang look at that a_value
  1. 配合使用
#需要一个构建时变量
ARG A_VARIABLE
#使用该值设置ENV var默认值
ENV an_env_var=$A_VARIABLE
#如果不被覆盖,您的容器将继续使用an_env_var的值!

RUN

  1. 解释

它接受命令作为参数并用于创建镜像。RUN会在shell或者exec的环境下执行命令。

例:RUN cd /opt
RUN echo helloworld
RUN [“命令”,“参数1”,“参数2”]   #可以免除运行/bin/sh的消耗,如果参数中引号等特殊字符,需要进行转义

ADD,COPY

  1. 解释

ADD:ADD和COPY作用相似,可以从一个URL地址下载内容复制到容器的文件系统中,还可以将压缩打包格式的文件解压后复制到指定位置。
文件复制均使用 COPY 指令,在需要自动解压缩的场合使用 ADD
COPY:用来将本地的文件或者文件夹复制到镜像的指定路径下,但是不会解压

COPY /local/path/file /images/path/file
ADD file /images/path/file
ADD latest.tar.gz /var/www

EXPOSE

  1. 解释

标明这个镜像中的应用将会监听某个端口,并且希望能将这个端口映射到主机的网络界面上,使容器内的应用可以通过端口和外界交互。
这里只是暴露了容器的端口,具体指定映射需要在运行容器的时候指定-p(小写)。

例:EXPOSE 80 443  多个端口空格隔开

ENTRYPOINT,CMD

1.ENTRYPOINT 解释

类似CMD配置容器启动后执行的命令,但是它不可被 docker run 提供的参数覆盖;
每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效

  1. ENTRYPOINT例:
ENTRYPOINT [ "sh", "-c", "echo $HOME" ]
ENTRYPOINT ["executable", "param1", "param2"]  #exec 格式
ENTRYPOINT command param1 param2   #shell格式
1.Exec 格式 
这种格式在容器run的时候指定的命令会覆盖ENTRYPOINT,CMD同样会覆盖
ENTRYPOINT 的 Exec 格式用于设置要执行的命令及其参数,同时可通过 CMD 提供额外的参数。 
ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉。 
2.Shell 格式 
ENTRYPOINT 的 Shell 格式会忽略任何 CMD 或 docker run 提供的参数。

Dockerfile 片段: 
ENTRYPOINT ["/bin/echo", "Hello"]   
CMD ["world"] 
#当容器通过 docker run -it [image] 启动时,输出为: 
Hello world 
#而如果通过 docker run -it [image] haha启动,则输出为: 
Hello haha
  1. CMD解释

CMD和RUN命令相似,CMD可以用于执行特定的命令。CMD每次启动容器时运行,RUN在创建镜像时执行一次,固化在image中。RUN命令先于CMD和ENTRYPOINT。
Dockerfile只允许使用一次CMD指令,一般都是脚本中最后一条指令。
如果docker run后面出现与CMD指定的相同的命令,那么CMD就会被覆盖。而ENTRYPOINT会把容器名后面的所有内容都当成参数传递给其指定的命令
CMD:设置镜像在启动容器时执行的命令。

  1. CMD例:
CMD ["sbin/nginx","-g","daemon off;"]
CMD ["executable","param1","param2"]  #CMD 的推荐格式。 
CMD ["param1","param2"] #为 ENTRYPOINT 提供额外的参数,此时 ENTRYPOINT 必须使用 Exec 格式。 
CMD command param1 param2  #Shell 格式

STOPSIGNAL(停止)

  1. 解释

该STOPSIGNAL指令设置将被发送到容器退出的系统调用信号。该信号可以是与内核syscall表中的位置匹配的有效无符号数字(例如9),也可以是格式为SIGNAME的信号名称(例如SIGKILL)。

默认的stop-signal是SIGTERM,在docker stop的时候会给容器内PID为1的进程发送这个signal,通过--stop-signal可以设置自己需要的signal,主要的目的是为了让容器内的应用程序在接收到signal之后可以先做一些事情,实现容器的平滑退出,如果不做任何处理,容器将在一段时间之后强制退出,会造成业务的强制中断,这个时间默认是10s。

#STOPSIGNAL 信号
STOPSIGNAL 9

ONBUILD

  1. 解释

为镜像添加触发器。其指令在构建镜像时候并不执行,而是在其子镜像中执行
当我们在一个Dockerfile文件中加上ONBUILD指令,该指令对利用该Dockerfile构建镜像(比如为A镜像)不会产生实质性影响。但是当我们编写一个新的Dockerfile文件来基于A镜像构建一个镜像(比如为B镜像)时,这时构造A镜像的Dockerfile文件中的ONBUILD指令就生效了,在构建B镜像的过程中,首先会执行ONBUILD指令指定的指令,然后才会执行其它指令。需要注意的是,如果是再利用B镜像构造新的镜像时,那个ONBUILD指令就无效了,也就是说只能再构建子镜像中执行,对孙子镜像构建无效。

FROM ubuntu:14.04
ONBUILD RUN echo “you not see me later”

基于dockerfile构建镜像命令

1. 指定其他路径的dockerfile
docker build -t 镜像名:tag -f dockerfile文件 .
2. 本目录构建镜像
docker build -t 镜像名:tag .
docker build -t  仓库名/镜像名:tag .
3. 可以将一个dockerfile构建成不同名称的镜像
docker build -t 镜像名01:tag01 -t 镜像名02:tag02 .
docker build -t  仓库名01/镜像名01:tag01 -t 仓库名02/镜像名02:tag02 .

基于dockerfile制作nginx镜像

dockerfile文件分类

mkdir -p /opt/dockerfile/{web/{nginx,tomcat,php,jdk,apache},system/{centos,ubuntu,redhat}}

Nginx yum安装Dockerfile内容

#Docker image for nginx
FROM centos:7.7.1908
LABEL description=timerovers<18932665502@163.com>
ENV NGINX-VERSION nginx-1.16.1
RUN yum -y install epel-release && yum -y install $NGINX-VERSION

Nginx编译安装Dockerfile内容

准备好nginx-1.16.1.tar.gz放到构建镜像的目录

#Docker image for nginx
FROM centos:7.7.1908
LABEL description=timerovers<18932665502@163.com>
ARG NGINX-VERSION=nginx-1.16.1
RUN yum -y install epel-release && yum -y install gcc gcc-c++ automake pcre pcre-devel zlib \ 
    zlib-devel openssl openssl-devel libxml2 libxml2-dev libxslt-devel gd-devel perl-devel \
    perl-ExtUtils-Embed GeoIP GeoIP-devel GeoIP-data
ADD  $NGINX-VERSION.tar.gz /usr/local/src/
RUN cd /usr/local/src/$NGINX-VERSION && useradd -M -s /sbin/nologin nginx \ 
        && ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx  \
    --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module \
    --with-http_realip_module --with-http_addition_module --with-http_xslt_module \
    --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module \
    --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module \
    --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module \
    --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module \
    && make && make install && yum clean all && rm -rf /usr/local/src/$NGINX-VERSION
EXPOSE 80
EXPOSE 443
WORKDIR /usr/local/nginx/
CMD ["sbin/nginx","-g","daemon off;"]

启动生成镜像

把配置和存放代码的目录映射出来
nginx-data可以提前创建好
docker run -d -p 50000:80 -p 50001:443 -v nginx-data:/usr/local/nginx --name nginx nginx:1.14.2
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容