命令记不住

登陆

Dockerfile 构建镜像

Dockerfile构建镜像

1.ockerfile自动构建docker镜像

dockerfile 支持自定义容器的初始命令

dockerfile主要组成部分:

  • 基础镜像信息 FROM centos:6.9
  • 制作镜像操作指令 RUN yum install openssh-server -y
  • 容器启动时执行指令 CMD ["/bin/bash"]

dockerfile常用指令:

  • FROM 这个镜像的妈妈是谁?(指定基础镜像)
  • MAINTAINER 告诉别人,谁负责养它?(指定维护者信息,可以没有)
  • LABLE 标签
  • RUN 你想让它干啥(在命令前面加上RUN即可)
  • ADD 给它点创业资金(会自动解压 tar) 制作docker基础的系统镜像
  • WORKDIR 我是cd,今天刚化了妆(设置当前工作目录)
  • VOLUME 给它一个存放行李的地方(设置卷,挂载主机目录)
  • EXPOSE 它要打开的门是啥(指定对外的端口)(-P 随机端口)
  • CMD 奔跑吧,兄弟!(指定容器启动后的要干的事情)(容易被替换)

dockerfile其他指令:

  • COPY 复制文件(不会解压)
  • ENV 环境变量
  • ENTRYPOINT 容器启动后执行的命令(无法被替换,启容器的时候指定的命令,会被当成参数)

4.参考其他的dockerfile
官方dockerfile或者时速云镜像广场

2.指令详解释

COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径

格式:

COPY [--chown=<user>:<group>] <源路径1> 。。。 <目标路径>

[--chown=:] 可选参数,用户改变复制到容器内文件的拥有者和属组

<源路径> 源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足Go的filepath.Match规则,例如

COPY  hom*  /mydir/
COPY  hom?.txt  /mydir/

<目标路径> 容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建

ADD

ADD指令和COPY的使用格式一致,功能也类型,不同之处如下:

  • ADD的优点:在执行<源文件>为tar压缩文件的话,压缩格式为gzip,bzip2以及xz的情况下,会自动复制解压到<目标路径>
  • ADD的缺点:在不解压的前提下,无法复制tar压缩文件,会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢,具体的使用,可以根据是否需要自动解压来决定
CMD

类似于RUN指令,用于运行程序,但二者运行的时间不同

  • CMD 在docker run时运行
  • RUN 是在docker build

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD指令指定的程序可以被docker run命令行参数中指定要运行的程序所覆盖

注意:如果Dockerfile中如果存在多个CMD指令,仅最后一个生效

格式

CMD <shell命令>
CMD ["可执行文件或命令","param1","param2",.....]
CMD ["<param1>","<param2>",...] #该写法是为ENIRYPOINT指令的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是sh

ENTRYPOINT

类似于CMD指令,但其不会被docker run 的命令参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给ENTRYPOINT指令指定的程序

但是,如果运行docker run时候用了 --entrypoint 选项,将覆盖CMD指令指定的程序

  • 优点:在执行docker run的时候可以指定ENTRYPOINT运行所需的参数
  • 注意:如果Dockerfile只存在多个ENTRYPOINT指令,仅最后一个生效

格式:

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配CMD命令使用:一般是变参才会使用CMD,这里的CMD等于是在给ENTRYPOINT传参,以下示例会提到

FROM  nginx
ENTRYPOINT  ["nginx","-c"] #定参
CMD  ["/etc/nginx/nginx.conf"]  #变参

1.不传参运行

$ docker run nginx:test

容器内会默认运行以下命令,启动主进程
nginx -c /etc/nginx/nginx.conf

2.传参运行

$ docker run  nginx:test  -c  /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf)
nginx -c /etc/nginx/new.conf
ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量

格式

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

以下示例设置NODE_VERSION = 7.2.0,在后续的指令中可以通过$NODE_VERSION引用:

ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" \
&& curl  -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.txt"
ARG

构建参数,与ENV作用一致,不过作用域不一样,ARG设置的环境变量仅对Dockerfile内有效,也就是说只有docker build的过程中有效,构建好的镜像内不存在此环境变量

构建命令docker build中可以用 --build-arg <参数名>=<值>来覆盖

ARG <参数名>[=<默认值>]
VOLUME

定义匿名数据卷,在启动容器时忘记挂载数据卷,会自动挂载到匿名卷

作用:

  • 避免重要的数据,因为容器重启而丢失,这是非常致命的
  • 避免容器不断变大

格式

VOLUME  ["路径1","路径2"]
VOLUME <路径>

在启动容器docker run的时候,我们可以通过-v参数修改挂载点

EXPOSE

仅仅只是声明端口

作用

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射
  • 在运行时使用随机端口映射时,也就是docker run -P时,会自动随机映射EXPOSE的端口
EXPOSE <端口1> [<端口2>...]
WORKDIR

指定工作目录。用WORKDIR指定的工作目录,会在构建镜像的每一层中都存在。WORKDIR指定的工作目录,必须是提前创建好的

docker build构建镜像过程中,每一个RUN命令都是新建的一层,只有通过WORKDIR创建的目录才会一直存在

WORKDIR <工作目录>
USER

用于指定执行后续命令的用户和用户组,这边只是切换后续命令的用户(用户和用户组必须提前已经存在)

USER <用户名>[:<用户组>]
HEALTHCHECK

用于指定某个程序或者指令来监控docker容器服务的运行状态

HEALTHCHECK [选项] CMD <命令> :设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉健康检查指令
HEALTHCHECK [选项] CMD <命令>:这边CMD后面跟随的命令使用
ONBUILD

用于延迟构建命令的执行。简单的说,就是Dockerfile里面用ONBUILD指定的命令,在本次构建镜像的过程中不会执行,当有心的Dockerfile使用了之前构建的镜像,这时执行心镜像的Dockerfile构建时候,会执行ONBUILD指定的命令

LABEL

LABEL指令用来给镜像添加一些元数据,以键值对的形式,语法格式如下

LABEL <key>=<value> <key>=<value>

3.相似命令间的区别

1.RUN 和 CMD

RUN 用于docker build,RUN可以使用多次,每次都是一层镜像
CMD 用于docker run,多个CMD只有最后一条生效,CMD会被docker run 命令行参数中指定要运行的程序所覆盖

2.ADD 和 COPY

使用格式一样,功能也类型,官方建议使用COPY
优点:在执行源文件是tar压缩文件的话,压缩格式为gzip,bzip2,xz的情况下,会自动复制并解压到目标路径
缺点:在不解压的前提下,无法复制tar文件,会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢

3.CMD 和 ENTRYPOINT

CMD和ENTRYPOINT都是如果存在多个,只有最后一个生效
ENTRYPOINT不会被docker run的命令行参数指定的指令覆盖,而且这些命令行参数会被当作参数送给ENTRYPOINT指令指定的程序,但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序。
优点:在执行docker run的时候可以指定ENTRYPOINT运行所需的参数
可以搭配CMD命令使用:一般是变参才会使用CMD,这里的CMD等于是在给ENTRYPOINT传参
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参 

4.ENV 和 ARG

他们的作用域不一样
ENV定义了环境变量,那么在后续的指令中,就可以使用这个环境变量
ARG环境变量仅对 Dockerfile 内有效

4.dockerfile制作镜像

第一步:编写dockerfile
第二步:docker build 构建镜像
第三部:测试

实例1

1.创建存放dockerfile的文件夹,并建立dockerfile文件

[root@docker01 dockerfile]# cat dockerfile 
FROM centos:6.9
RUN yum install openssh-server -y
RUN service sshd start
RUN echo '123456'|passwd --stdin root
CMD ["/usr/sbin/sshd","-D"]

2.构建镜像

[root@docker01 dockerfile]# docker image build -t centos6.9_ssh:v1 .

//在当前目录构建

3.测试镜像

[root@docker01 dockerfile]# docker run -d -p 2222:22 centos6.9_ssh:v1

示例2

2.1.创建dockerfile

[root@docker01 dockerfile]# cat dockerfile 
FROM centos:6.9
RUN yum install openssh-server -y
RUN service sshd start
RUN echo '123456'|passwd --stdin root
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
RUN yum install nginx -y
ADD start.sh /start.sh              // 添加与dockerfile同级目录下的init.sh脚本到docker镜像的根目录
EXPOSE 80 22
VOLUME /usr/share/nginx/html
WORKDIR /usr/share/nginx/html       // build镜像过程中,RUN提交镜像时当前目录不会发生改变
CMD ["/bin/bash","/start.sh"]

2.2.创建脚本
docker在启动容器的时候只运行一条命令,所以多服务启动需要用脚本启动

[root@docker01 dockerfile]# cat init.sh
#!/bin/bash 
service nginx start 
/usr/sbin/sshd -D 

2.3.构建镜像

[root@docker01 abc]# docker image build -t centos6.9_ssh_nginx:v15 .

示例3

3.ENV的使用(脚本传参)可以让镜像变的很灵活
3.1.ENTRYPOINT代替CMD的写法

[root@docker01 dockerfile]# cat dockerfile 
FROM centos:6.9
RUN yum install openssh-server -y
RUN service sshd start
ENV  SSH_PASS 123456
COPY init.sh /init.sh
ENTRYPOINT ["/usr/sbin/sshd","-D"]

[root@docker01 dockerfile]# cat init.sh 
#!/bin/bash
echo '$SSH_PASS' |passwd --stdin root

[root@docker01 dockerfile]# docker run -d --env 'SSH_PASS=1QWE#@!10' -P 7022:22 centos6.9:v1

4.Volume持久化

[root@docker01 centos6.9_ssh_nginx]# docker volume  ls
DRIVER              VOLUME NAME
local               x86cloud

[root@docker01 centos6.9_ssh_nginx]# docker volume inspect x86cloud 
[
    {
        "CreatedAt": "2019-02-24T01:59:15+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/x86cloud/_data",
        "Name": "x86cloud",
        "Options": {},
        "Scope": "local"
    }
]

推荐阅读