Dockerfile文件

一、 概述

Dockfile文件是镜像生成的一种方式。Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 快速创建自定义的镜像。Dockerfile文件中的每一个命令都会创建镜像的一层。

二、常见命令

命令字作用语法
FROM指定基础镜像,并且必须是第一条指令。FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>
RUN镜像创建时运行指定的命令。
注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层.
多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。
linux操作系统上默认 /bin/sh -c
RUN书写时的换行符是 \
RUN command
RUN [“executable”, “param1”, “param2”]
CMD功能为容器启动时要运行的命令.
注意:里边包括参数的一定要用双引号,就是",不能是单引号。千万不能写成单引号。
原因是参数传递后,docker解析的是一个JSON array
CMD [“executable”,“param1”,“param2”]
CMD [“param1”,“param2”]
CMD command param1 param2
LABEL为镜像指定标签,一个Dockerfile种可以有多个LABEL
注意:LABEL会继承基础镜像中的LABEL,如遇到key相同,则值覆盖
LABEL <key>=<value> <key>=<value> <key>=<value>
MAINTAINER指定作者MAINTAINER name
EXPOSE暴漏容器运行时的监听端口给外部,但是EXPOSE并不会使容器访问主机的端口EXPOSE port
ENV设置环境变量,多环境变量使用空格隔开ENV
ENV = = =…
ADD把文件复制到镜像中;如果把<src>写成一个url,那么ADD就类似于wget命令;
尽量不要把<scr>写成一个文件夹,如果<src>是一个文件夹了,复制整个目录的内容,包括文件系统元数据
能够将压缩文件自动解压
ADD …
ADD [“”,… “”]
SHELL设置默认的 shell 环境。默认情况下,Docker 使用 /bin/sh -cSHELL [“”, “<shell参数>”]
COPY把文件复制到镜像中;
与ADD的区别:COPY的<src>只能是本地文件,其他用法一致
COPY …
COPY [“”,… “”]
ENTRYPOINT容器启动时的默认命令;
与CMD比较说明:
相同点:
只能写一条,如果写了多条,那么只有最后一条生效
容器启动时才运行,运行时机相同
不同点:
ENTRYPOINT不会被docker run运行的command覆盖,而CMD则会被覆盖
如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数
如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效。
ENTRYPOINT [“executable”, “param1”, “param2”]
ENTRYPOINT command param1 param2
VOLUME实现挂载功能,可以将内部文件夹或者其他容器中得文件夹挂载到这个容器中,一般的使用场景为需要持久化存储数据时;
[“/data”]可以是一个JsonArray ,也可以是多个值。所以如下几种写法都是正确的
VOLUME [“/var/log/”]
VOLUME /var/log
VOLUME /var/log /var/db
注意:VOLUME命令在Dockerfile中只能用来创建挂载点,不能指定已经存在的目录作为挂载点。如果指定的目录已经存在,但没有使用VOLUME命令,Docker将会将其作为普通目录对待,而不会创建一个挂载点。
VOLUME [“/data”]
USER设置启动容器的用户,可以是用户名或UID
注意:如果设置了容器以daemon用户去运行,那么RUN, CMD 和 ENTRYPOINT 都会以这个用户去运行
USER daemo
USER UID
WORKDIR设置工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次;默认工作目录是:/WORKDIR /path/to/workdir
ARG设置变量命令,ARG命令定义了一个变量;在docker build创建镜像的时候,使用 --build-arg <varname>=<value>来指定参数;如果用户在build镜像时指定了一个参数没有定义在Dockerfile种,那么将有一个Warning
提示如下:
[Warning] One or more build-args [foo] were not consumed.
如果我们给了ARG定义的参数默认值,那么当build镜像时没有指定参数值,将会使用这个默认值
ARG <name>[=<default value>]
STOPSIGNAL当容器退出时给系统发送什么样的指令STOPSIGNAL signal
HEALTHCHECK容器健康状况检查命令;
第一个的功能是在容器内部运行一个命令来检查容器的健康状况 第二个的功能是在基础镜像中取消健康检查命令 [OPTIONS]的选项支持以下三中选项:
interval=DURATION 两次检查默认的时间间隔为30秒
timeout=DURATION 健康检查命令运行超时时长,默认30秒
retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3
注意:
HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。
CMD后边的命令的返回值决定了本次健康检查是否成功,具体的返回值如下:
0: success - 表示容器是健康的
1: unhealthy - 表示容器已经不能工作了
2: reserved - 保留值
HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE

2.1 FROM

指定基础镜像,必须为第一个命令

格式:
  FROM <image>
  FROM <image>:<tag>
  FROM <image>@<digest>

示例:  
	FROM mysql:5.6
注:
   tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像

2.2 MAINTAINER(新版即将废弃)

维护者信息

格式:
    MAINTAINER <name>
示例:
    MAINTAINER bertwu
    MAINTAINER xxx@162.com
    MAINTAINER bertwu <xxx@162.com>

2.3 RUN

构建镜像时执行的命令

RUN用于在构建镜像时执行命令,其有以下两种命令执行方式:
shell执行
格式:
    RUN <command>
exec执行
格式:
    RUN ["executable", "param1", "param2"]
示例:
    RUN ["executable", "param1", "param2"]
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]
注:RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,
可以在构建时指定--no-cache参数,如:docker build --no-cache

2.4 ADD

将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget

格式:
    ADD <src>... <dest>
    ADD ["<src>",... "<dest>"] 用于支持包含空格的路径
示例:
    ADD hom* /mydir/          # 添加所有以"hom"开头的文件
    ADD hom?.txt /mydir/      # ? 替代一个单字符,例如:"home.txt"
    ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
    ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/

2.5 COPY

功能类似ADD,但是是不会自动解压文件,也不能访问网络资源

2.6 CMD

构建镜像后调用,也就是在容器启动时才进行调用。

格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
示例:
    CMD echo "This is a test." | wc -l
    CMD ["/usr/bin/wc","--help"]

注:CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

2.7 ENTRYPOINT

配置容器,使其可执行化。配合CMD可省去"application",只使用参数。

格式:
    ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
    ENTRYPOINT command param1 param2 (shell内部命令)
示例:
    FROM ubuntu
    ENTRYPOINT ["ls", "/usr/local"]
    CMD ["/usr/local/tomcat"]
  之后,docker run 传递的参数,都会先覆盖cmd,然后由cmd 传递给entrypoint ,做到灵活应用

注:ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,
 而docker run命令中指定的任何参数,都会被当做参数再次传递给CMD。
 Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,
 而只执行最后的ENTRYPOINT指令。
 通常情况下,	ENTRYPOINT 与CMD一起使用,ENTRYPOINT 写默认命令,当需要参数时候 使用CMD传参


2.8 LABEL

用于为镜像添加元数据

格式:
    LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
  LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
注:
  使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据
  之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。

2.9 ENV

设置环境变量

格式:
    ENV <key> <value>  #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
    ENV <key>=<value> ...  #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
    ENV myName John Doe
    ENV myDog Rex The Dog	
    ENV myCat=fluffy

2.10 EXPOSE

指定于外界交互的端口

格式:
    EXPOSE <port> [<port>...]
示例:
    EXPOSE 80 443
    EXPOSE 8080    
    EXPOSE 11211/tcp 11211/udp
注:  EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

如果没有暴露端口,后期也可以通过-p 8080:80方式映射端口,但是不能通过-P形式映射

2.11 VOLUME

用于指定持久化目录(指定此目录可以被挂载出去)

格式:
    VOLUME ["/path/to/dir"]
示例:
    VOLUME ["/data"]
    VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
注:一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
1 卷可以容器间共享和重用
2 容器并不一定要和其它容器共享卷
3 修改卷后会立即生效
4 对卷的修改不会对镜像产生影响
5 卷会一直存在,直到没有任何容器在使用它

2.12 WORKDIR

工作目录,类似于cd命令

格式:
    WORKDIR /path/to/workdir
示例:
    WORKDIR /a  (这时工作目录为/a)
    WORKDIR b  (这时工作目录为/a/b)
    WORKDIR c  (这时工作目录为/a/b/c)
注: 
  通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY
  等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

2.13 USER

指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户

格式:  
USER user  
USER user:group  
USER uid  
USER uid:gid  
USER user:gid  
USER uid:group

示例:      
     USER www
 注:
  使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。
  镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

2.14 ARG

用于指定传递给构建运行时的变量(给dockerfile传参),相当于构建镜像时可以在外部为里面传参

格式:
    ARG <name>[=<default value>]
示例:
    ARG site
    ARG build_user=www
From centos:7
ARG parameter
VOLUME /usr/share/nginx
RUN yum -y install $parameter
EXPOSE 80 443
CMD nginx -g "daemon off;"

# 可以这如下这样灵活传参

docker build --build-arg=parameter=net-tools -t nginx:01 . 

2.15 ONBUILD

用于设置镜像触发器

格式: 
	ONBUILD [INSTRUCTION]
示例:
  ONBUILD ADD . /app/src
  ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注:
  ONBUID后面跟指令,当当前的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被动触发

三、制作镜像

编写dockerfile文件
FROM ubuntu
RUN apt update && apt install -y gcc make wget && apt install -y libpcre3 libpcre3-dev zlib1g-dev openssl libssl-dev
RUN wget http://nginx.org/download/nginx-1.24.0.tar.gz && tar xf nginx-1.24.0.tar.gz && cd nginx-1.24.0 && ./configure --prefix=/usr/local/nginx && make && make install
EXPOSE  80
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]

# This my first nginx Dockerfile
# Version 1.0

# Base images 基础镜像
FROM centos:7

#MAINTAINER 维护者信息
MAINTAINER bertwu 

#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH

#ADD  文件放在当前目录下,拷过去会自动解压
ADD nginx-1.8.0.tar.gz /usr/local/  
ADD epel-release-latest-7.noarch.rpm /usr/local/  

#RUN 执行以下命令 
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all
RUN useradd -s /sbin/nologin -M www

#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.8.0 

RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install

RUN echo "daemon off;" >> /etc/nginx.conf

#EXPOSE 映射端口
EXPOSE 80

#CMD 运行以下命令
CMD ["nginx"]
构建镜像

docker build命令解析

  1. -t, --tag: 给镜像打标签,格式为 name:tag

    docker build -t myimage:latest .
    
  2. -f, --file: 指定 Dockerfile 的路径。

    docker build -f /path/to/Dockerfile .
    
  3. –build-arg: 设置构建参数,可以在 Dockerfile 中使用 ARG 指令引用。

    docker build --build-arg MY_VAR=value .
    
  4. –no-cache: 不使用缓存,强制重新构建所有层。

    docker build --no-cache .
    
  5. –pull: 总是尝试拉取最新的基础镜像。

    docker build --pull .
    
  6. –compress: 使用 gzip 压缩构建上下文。

    docker build --compress .
    
  7. –quiet, -q: 静默模式,只输出镜像 ID。

    docker build -q .
    
  8. –target: 指定构建阶段,适用于多阶段构建。

    docker build --target mystage .
    
  9. –network: 指定构建过程中使用的网络模式。

    docker build --network mynetwork .
    
  10. –label: 给镜像添加元数据标签。

    docker build --label version=1.0 .
    

例如,如果你想构建一个带有特定标签和构建参数的镜像,可以使用以下命令:

docker build -t myimage:1.0 --build-arg MY_VAR=value .

这样,你就可以在 Dockerfile 中使用 ARG MY_VAR 来引用 MY_VAR 的值。

四、课后作业

1. LNMP容器化后部署discuz论坛,并能够成功访问。
2. Redis集群容器化,并能够实现外部连接。

mysql8的官方容器镜像,远程登录认证模块有异常需要更改远程用户登录认证方式:

alter user 'admin'@'%' identified with mysql_native_password by '123.com';

mysql8的用户赋权需要先创建用户再进行赋权:

create user 'admin'@'%' identified by '123.com';
grant all on *.* to 'admin'@'%';

yimage:1.0 --build-arg MY_VAR=value .


这样,你就可以在 Dockerfile 中使用 `ARG MY_VAR` 来引用 `MY_VAR` 的值。

## 四、课后作业

```apl
1. LNMP容器化后部署discuz论坛,并能够成功访问。
2. Redis集群容器化,并能够实现外部连接。

mysql8的官方容器镜像,远程登录认证模块有异常需要更改远程用户登录认证方式:

alter user 'admin'@'%' identified with mysql_native_password by '123.com';

mysql8的用户赋权需要先创建用户再进行赋权:

create user 'admin'@'%' identified by '123.com';
grant all on *.* to 'admin'@'%';

更多推荐