• 欢迎访问春风博客

使用 dockerfile 来构建自己的镜像

运维笔记 xiaogang 2年前 (2022-08-09) 1085次浏览 0个评论

Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

Dockerfile 示例

#基础镜像
FROM ubuntu
#添加文件到镜像
COPY ./GatewayWorkerNew /www/server/GatewayWorker
COPY start.sh /home/start.sh
COPY php.ini /www/server/php/74/etc/php.ini
#构架镜像时运行命理
RUN chmod +x /home/start.sh && \
    rm -f /install.sh

#为镜像添加匿名卷
VOLUME ["/www/server/mysqlData","/www/backup","/www/wwwlogs","/www/wwwroot"]
#暴露端口
EXPOSE 80 443 9706 888
#容器启动命令
CMD ["sh","/home/start.sh"]

FROM 指定基础镜像

所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。

这里我使用 ubuntu 作为基础镜像,你可以指定版本号比如 FROM ubuntu:20.04 不指定时默认使用 latest 版本,基础镜像是必须指定的。而 FROM 就是指定 基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。

COPY 的文件/目录复制到镜像内

格式 COPY [–chown=<user>:<group>] <源路径>… <目标路径>

拷贝文件到指定目录
COPY start.sh /home/start.sh

拷贝目录
COPY ./GatewayWorkerNew /www/server/GatewayWorker

在使用该指令的时候还可以加上 –chown=<user>:<group> 选项来改变文件的所属用户及所属组。
COPY –chown=55:mygroup files* /mydir/
COPY –chown=bin files* /mydir/
COPY –chown=1 files* /mydir/
COPY –chown=10:11 files* /mydir/

RUN 在定制镜像时是执行的命令行

在使用RUN命理时应该把命令整合为一条,Dockerfile 中每一个指令都会建立一层镜像,所以应该把命令使用 && 链接为一条命令。
RUN chmod +x /home/start.sh && \
rm -f /install.sh

VOLUME 定义匿名卷

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中了,防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

VOLUME [“/www/server/mysqlData”,”/www/backup”,”/www/wwwlogs”,”/www/wwwroot”]

VOLUME /www/server/mysqlData

以上两种写法都是可以的

EXPOSE 暴露端口

格式为:EXPOSE <端口1> [<端口2>…]
EXPOSE 指令是声明容器运行时提供服务的端口,这只是一个声明,在容器运行时并不会因为这个声明应用就会开启这个端口的服务。

在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。

CMD 容器启动命令

Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。
提到 CMD 就不得不提容器中应用在前台执行和后台执行的问题。这是初学者常出现的一个混淆。
Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 systemd 去启动后台服务,容器内没有后台服务的概念。

一些初学者将 CMD 写为:
CMD service nginx start

然后发现容器执行后就立即退出了。甚至在容器内去使用 systemctl 命令结果却发现根本执行不了。
这就是因为没有搞明白前台、后台的概念,没有区分容器和虚拟机的差异,依旧在以传统虚拟机的角度去理解容器。

对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。

而使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为 CMD [ “sh”, “-c”, “service nginx start”],因此主进程实际上是 sh。那么当 service nginx start 命令结束后,sh 也就结束了,sh 作为主进程退出了,自然就会令容器退出。

正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:
CMD [“nginx”, “-g”, “daemon off;”]

使用dockerfile文件构造镜像

docker build –pull –rm -f dockerfile -t ubuntu:20220809

build参数说明

–build-arg=[] :设置镜像创建时的变量;

–cpu-shares :设置 cpu 使用权重;

–cpu-period :限制 CPU CFS周期;

–cpu-quota :限制 CPU CFS配额;

–cpuset-cpus :指定使用的CPU id;

–cpuset-mems :指定使用的内存 id;

–disable-content-trust :忽略校验,默认开启;

-f :指定要使用的Dockerfile路径;

–force-rm :设置镜像过程中删除中间容器;

–isolation :使用容器隔离技术;

–label=[] :设置镜像使用的元数据;

-m :设置内存最大值;

–memory-swap :设置Swap的最大值为内存+swap,”-1″表示不限swap;

–no-cache :创建镜像的过程不使用缓存;

–pull :尝试去更新镜像的新版本;

–quiet, -q :安静模式,成功后只输出镜像 ID;

–rm :设置镜像成功后删除中间容器;

–shm-size :设置/dev/shm的大小,默认值是64M;

–ulimit :Ulimit配置。

–squash :将 Dockerfile 中所有的操作压缩为一层。

–tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。

–network: 默认 default。在构建期间设置RUN指令的网络模式

Dockerfile 指令表

指令 使用方法 描述
FROM FROM ubuntu 指定基础镜像
RUN RUN apt update -y 构架镜像时执行的命令
COPY COPY /dir /mydir/                     COPY –chown=www:nginx /dir /mydir/ 文件/目录复制到镜像内 可指定文件的所属用户及所属组
ADD ADD mydata.tar.gz /data                COPY /dir /mydir/                     COPY –chown=www:nginx /dir /mydir/ ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。另外需要注意的是,ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。
ENV ENV VERSION=1.0 DEBUG=on \
NAME=”Happy Feet”
ENV 设置环境变量
ARG ARG DOCKER_USERNAME=ubuntu

FROM ${DOCKER_USERNAME}/22.04            上面使用过以后就失效了,如果后面还需要使用需要再次指定

ARG 构建参数 构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的
VOLUME VOLUME [“/data1″,”/data2”] 容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中,为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据
EXPOSE EXPOSE 80 443 EXPOSE 指令是声明容器运行时提供服务的端口,这只是一个声明,在容器运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
WORKDIR WORKDIR /home 指定工作目录,以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。
USER USER redis 指定当前用户,改变之后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。
LABEL LABEL org.opencontainers.image.authors=”chunblog” LABEL 指令用来给镜像以键值对的形式添加一些元数据(metadata)
SHELL SHELL [“/bin/sh”, “-c”] SHELL 指令可以指定 RUN ENTRYPOINT CMD 指令的 shell
ONBUILD ONBUILD RUN [ “npm”, “install” ] ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
HEALTHCHECK HEALTHCHECK [选项] CMD <命令> 健康检查
ENTRYPOINT ENTRYPOINT [ “ping”, “114.114.114.114” ] ENTRYPOINT 入口点,ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 –entrypoint 来指定。
CMD CMD [“bash”] 容器启动命令

 


ChunBlog.Com , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:使用 dockerfile 来构建自己的镜像
喜欢 (1)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址