docker学习(五)使用 Dockerfile 制作镜像

docker学习(一)docker 概述
docker学习(二)docker 安装部署
docker学习(三)常用命令
docker学习(四)使用 commit 制作镜像
docker学习(五)使用 Dockerfile 制作镜像
docker学习(六)卷 Volume
docker学习(七)docker daemon
docker学习(八)HTTP/HTTPS 代理
docker学习(九)docker 调试
docker学习(十)docker 持久化存储

使用Dockerfile制作镜像
制作Docker镜像,一般有两种方式:一种是commit方式,利用已有的镜像,运行后安装定制自己需要的环境,然后生成镜像;另一种就是build方式,通过编写Dockerfile命令脚本进行生成镜像。
本文介绍使用dockerfile制作镜像,并配置容器内程序自动启动。

概述

Dockerfile文件需放置在一个目录中,这个目录中有构建镜像的所有文件,是本次执行的上下文路目录(可以理解为docker根目录),可以创建子目录。
在Dockerfile文件中,"#“号开头表示注释,每行为"INSTRUCTION arguments”,习惯大写表示关键字(但并不区分大小写),后面小写表示值。
每个Dockerfile的第一行(注释行除外),必须使用"FROM"关键字。
当使用docker build构建镜像时,会将我们指定的上下文目录打包传递给docker引擎。这个上下文目录中并非所有文件都会在Dockerfile中使用,传送给docker引擎的目录过大会影响构建速度,可以在此目录中定义.dockerignore文件,将不使用的文件的文件名写入到.dockerignore文件屏蔽掉,且支持通配符。
最小化镜像的层数,Dockerfile中每一行命令就是一层,层数过多影响构建效率。
Dockerfile文件中命令从上往下逐行执行。

Dockerfile参数简介

FROM

指定哪种镜像作为新镜像的基础镜像:

FROM IMAGE [AS ALIAS]
# FROM…AS…: 这是Docker 17.05及以上版本新出来的指令,其实就是给这个阶段的镜像起个别名:FROM …(基础镜像) AS …(别名),在后面引用这个阶段的镜像时直接使用别名就可以了.
FROM centos:7
FROM centos:7 AS builder

MAINTAINER

指明该镜像的作者和其电子邮件:

MAINTAINER test "test@qq.com"

LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,使用docker inspect可查看镜像的相关信息,语法格式如下:

LABEL <key>=<value> [<key>=<value> <key>=<value> ...]
LABEL maintainer="test <test@qq.com>"
LABEL version="1.0"
LABEL description="这是我的Dockerfile"
# 或者
LABEL maintainer="test <test@qq.com>" description="这是我的Dockerfile"

EXPOSE

声明端口。帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
格式:

EXPOSE <port1> [<port2>...]
EXPOSE 1935/tcp \
			554/tcp \
			80/tcp

WORKDIR

指定工作目录。该工作目录会在构建镜像的每一层中都存在。以后各层的工作目录就被改为该目录,如该目录不存在,WORKDIR 会创建目录。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
格式:

WORKDIR <path>
# 会创建 /opt/zlm/目录
WORKDIR /opt/zlm/

ONBUILD

用于延迟构建命令的执行。简单的说,就是包含ONBUILD命令的镜像被用作其他镜像的基础镜像时,该命令就会执行。

ONBUILD <command>

如创建镜像image-A:

FROM centos:7
...
ONBUILD ADD . /var/www
...

然后创建镜像image-B,指定image-A为基础镜像:

FROM image-A
...

然后在构建image-B的时候,日志上显示如下:

Step 0 : FROM image-A
# Execting 1 build triggers
Step onbuild-0 : ADD . /var/www
...

USER

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

USER <user>[:<group>]

VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷,挂载在/var/lib/docker/volumes/*/_data。
避免重要的数据,因容器重启而丢失,这是非常致命的。
避免容器不断变大。

VOLUME ["<path1>", "<path2>"...]
VOLUME <path>
VOLUME [ "/opt/zlm/buid/conf/","/opt/zlm/build/log/"]
#主机/var/lib/docker/volumes/*1/_data-->/opt/zlm/buid/conf/
#主机/var/lib/docker/volumes/*2/_data-->/opt/zlm/buid/log/

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

ENV

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

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
ENV NODE_VERSION 7.2.0
ENV PATH=/opt/zlm/build/bin:$PATH

ARG

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

ARG <param>[=<default>]

该参数不会创建一层。

RUN

用于执行后面跟着的命令行命令,比如安装一些软件、配置一些基础环境,可使用\来换行。有以下两种格式:
shell 格式:

RUN <command>
# <command> 等同于,在终端操作的 shell 命令。
# 例如:
# RUN ./MediaServer -c ./config/config.ini
# RUN yum -y install redis

exec 格式:

RUN [“executable”, “param1”, “param2”]
# 例如:
# RUN ["./MediaServer", "-c", "./config/config.ini"]
# RUN ["apt-get","install","-y","redis"]

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.g

以上执行会创建 3 层镜像。可简化为以下格式:

FROM centos
RUN yum -y install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz

如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

COPY

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

COPY [OPTIONS] <srcpath1>...  <dstpath>
COPY [OPTIONS] ["<srcpath1>",...  "<dstpath>"]
#OPTIONS:
--chown=<user>:<group>:可选参数,改变复制到容器内文件的拥有者和属组。
--from=builder:可选参数,表示文件来源不是本地文件系统,而是FROM AS创建的别名为builder的容器。

:源文件或者源目录,需位于dockerfile所在目录,支持通配符表达式。例如:

COPY file* /opt/zlm/
COPY file?.txt /opt/zlm/

:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
ADD 的优点:在执行 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 。
ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件,因为自动删除了。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

ADD /build.tar.gz /opt/zlm/

CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
CMD 在docker run 时运行。
RUN 是在 docker build。
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

CMD <command> 
CMD ["<executable>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

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

ENTRYPOINT

这个参数表示镜像的“入口”,镜像打包完成之后,使用docker run命令运行时,其实就是执行ENTRYPOINT后面的可执行文件(一般是一个shell脚本文件)。
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

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

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

构建镜像实例

创建Dockerfile文件

# 定义参数,构建时使用
ARG Version=7

# 构建临时镜像
FROM centos:${Version} As builder

# 声明端口
EXPOSE 80/tcp \
    1935/tcp \
    554/tcp

ARG X265_VERSION=3.4

# 临时镜像安装依赖
RUN yum install -y  \
        wget \
        which

# 整理临时镜像的
WORKDIR /opt

# 仅供参考 使用ARG 
#RUN cd /opt \
#    && wget -e "https_proxy=${HTTPS_PROXY}" https://github.com/videolan/x265/archive/Release_${X265_VERSION}.tar.gz  \
#    && tar zxvf Release_${X265_VERSION}.tar.gz \
#    && cd x265-Release_${X265_VERSION}/build/linux \
#    && cmake ../../source \
#    && make -j8 \
#    && make install \
#    && export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH

RUN mkdir -p /opt/build/usr/bin/ \
    && cd /opt/build \
    && /usr/bin/cp -ip /usr/bin/which ./usr/bin/
	
# 以上构建临时镜像的步骤可以不要,主要学习COPY --frome 使用
#################################################
# 构建镜像
FROM centos:${Version}

# 添加镜像说明信息
LABEL maintainer="test <test@test.com>" description="hello world"

# 添加上下文目录中的build.tar.gz,到容器目录/opt/zlm
# 解压后有 MediaServer
ADD /build.tar.gz /opt/zlm/

# 从builder 拷贝
COPY --from=builder /opt/build/usr/bin/* /opt/zlm/build/

# 挂载卷
# /var/lib/docker/volumes/*1/_data -> /opt/zlm/build/conf/
# /var/lib/docker/volumes/*2/_data -> /opt/zlm/build/log/
VOLUME ["/opt/zlm/build/conf/", "/opt/zlm/build/log/"]

# 添加环境变量
ENV PATH=/opt/zlm/build/bin:$PATH
#ENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH TZ=Asia/Shanghai

# 切换工作目录
WORKDIR /opt/zlm/build

# 添加启动脚本
# 最后/bin/bash作用为,阻塞docker不退出
RUN touch start.sh \
    && echo "#!/bin/bash" >> start.sh \
    && echo "MediaServer -c ./config/config.ini &" >> start.sh \
    && echo "/bin/bash" >> start.sh \
    && chmod 777 start.sh

# 程序启动
# 该方式会捕获停止中断,而终止服务
#ENTRYPOINT ["MediaServer", "-c", "./config/config.ini", "&"]
# 该方式后台启动服务
ENTRYPOINT ["./start.sh"]

构建镜像与容器操作

# 构建镜像
sudo docker build -t centos7zlm:v1.0 -f ./Dockerfile ./
# 创建容器
sudo docker run -itd --rm --name centos7zlm-container -p 805:80 -p 5545:554 centos7zlm:v1.0
# 进入容器
sudo docker exec -it centos7zlm-container /bin/bash
# 停止容器(自动删除)
sudo docker stop centos7zlm-container
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值