docker学习Dockerfile写作
Posted 懒佯佯大哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了docker学习Dockerfile写作相关的知识,希望对你有一定的参考价值。
介绍
- Dockerfile是镜像制作的脚本,定义了镜像制作的过程
一个简单的示例:
- 创建一个空目录/tmp/test/:用于存放镜像构建相关文件
- 在该目录下,编写一个Dockerfile
zhaoyue@zhaoyuedeMacBook-Pro test % cat Dockerfile
FROM scratch
CMD /bin/bash
- 开始构建镜像
zhaoyue@zhaoyuedeMacBook-Pro test % docker build -f Dockerfile -t firstimage:1.0.0 .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM scratch
# 父镜像。scratch是base镜像,所有镜像的祖先,类似于java中的Object类一样
# DockerHub中很多镜像,都是以此镜像为基础
--->
Step 2/2 : CMD /bin/bash
---> Running in 7e3d94cf1358 # 每个命令都是一层layer
Removing intermediate container 7e3d94cf1358
---> fc0f384a1368
Successfully built fc0f384a1368
Successfully tagged firstimage:1.0.0
- docker images:查看制作的镜像
zhaoyue@zhaoyuedeMacBook-Pro test % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
firstimage 1.0.0 fc0f384a1368 7 minutes ago 0B
参数详细介绍
-
官方文档:https://docs.docker.com/engine/reference/builder/
-
.dockerignore文件,定义了制作时忽略的文件列表(类似于git里的.gitignore)
-
解释器参数,不会生成layer,这里不做详细介绍
-
FROM:当前构建的基础镜像来源,可指定架构信息
- FROM [–platform=] [AS ]
-
ARG:定义构建时的变量:
- 格式:ARG [=]
- docker在运行时可以通过:docker build --build-args xx=yy方式指定
- 另外,dockerfile已经预定了一些变量名称,可以直接使用:HTTP_PROXY、http_proxy、HTTPS_PROXY、https_proxy、FTP_PROXY、ftp_proxy、NO_PROXY、no_proxy
-
MAINTAIN:作者,一般包括姓名、邮箱—-已经弃用,官方建议使用LABEL
-
RUN:执行linux命令
- 格式1:RUN (shell形式,命令在shell中运行,默认情况下/bin/sh -c在Linux或cmd /S /CWindows 上运行)
- 格式2:RUN [“executable”, “param1”, “param2”]
- 由于每个命令都会生成一层layer,故多个命令时,建议使用&&进行连接,从而减少layer层数,便于维护
-
EXPOSE:该镜像启动时对外暴露的端口,可以通过protocol指定是TCP还是UDP
- EXPOSE [/…]
-
LABEL:向镜像中添加的元数据信息(多个key-value数据时,尽量合并成一行),可以通过docker inspect命令查看LABEL的信息
- LABEL = = = …
-
WORKDIR:创建容器后,终端默认登录进来的工作目录,如果没设置的话,则为根目录
-
ENV:设置环境变量,该命令也会生成layer,示例:ENV MY_PATH /home/admin
- ENV
- ENV = … # 这种可以设置多个值
- 也可通过docker run —env =动态修改
-
ADD:将宿主机的文件“拷贝+解压”(gzip,bzip2或xz)进镜像
- ADD [–chown=:] …
- ADD [–chown=:] ["",… “”]
- src路径设置的时候,可以按照Go的 filepath.Match通配规则
- 示例:ADD --chown=55:mygroup files* /somedir/
-
COPY:将宿主机的文件“拷贝”进镜像
- COPY [–chown=:] …
- COPY [–chown=:] ["",… “”]
- 备注:src中可含有满足filepath.Match的通配符
-
VOLUME:容器数据卷,用于保存和持久化操作
- 为了保证可移植性,这里只需指定容器中的路径,docker会在本地的默认路径生成一个映射目录
-
ONBUILD:当构建一个被继承的Dockerfile时运行:父镜像在被子镜像继承后会被触发
-
USER:指定运行命令的用户/组
- USER [:] group为可选
-
STOPSIGNAL
- STOPSIGNAL signal
- 该STOPSIGNAL指令设置将被发送到容器退出的系统调用信号。该信号可以是与内核syscall表中的位置匹配的有效无符号数字(例如9),也可以是格式为SIGNAME的信号名称(例如SIGKILL)。
-
CMD:容器启动时的运行命令以及参数,存在多个时只有最后一个生效
- CMD [“executable”,“param1”,“param2”](exec形式,这是首选形式)
- CMD [“param1”,“param2”](作为ENTRYPOINT的默认参数)
- CMD command param1 param2(外壳形式
- docker run时可加上命令,此时会覆盖掉CMD:docker run nginx ls
-
ENTRYPOINT:容器启动时的运行命令以及参数
- 可以通过docker run --entrypoint 覆盖执行
- ENTRYPOINT [“executable”, “param1”, “param2”]
- ENTRYPOINT command param1 param2
- 示例:ENTRYPOINT exec top -b
部分参数差异
- ARG vs ENV:
- ENV声明的变量,会始终存在于环境中
- 同名的情况下,ENV声明的覆盖掉ARG
- ARG用于build阶段,用–build-arg修改
- ENV用于run阶段,用–env修改
- CMD vs ENTRYPOINT:
- CMD的命令会被覆盖,以最后一个为准
- ENTRYPOINT会被追加,逐步追加到之前的命令上,然后作为一条完整命令执行
- 可以同时使用,一般将CMD写在后面,容器启动时,是将ENTRYPOINT和CMD的命令拼在一起执行,这样,既保证了ENTRYPOINT的灵活,也可保证CMD的唯一性
官网的示例
- 登录官网:hub.docker.com
- 搜索需要查找的镜像
- 进入查找的镜像,然后选中某一个版本,比如latest
- 示例1:centos
- https://github.com/CentOS/sig-cloud-instance-images/blob/52cc14a6dd2efc45265417a4690964d32cf13857/docker/Dockerfile
# 基础镜像
FROM scratch
# 将centos镜像拷贝、解压到根目录
ADD CentOS-8-Container-8.1.1911-20200113.3-layer.x86_64.tar.xz /
# 元数据信息
LABEL org.label-schema.schema-version="1.0" \\
org.label-schema.name="CentOS Base Image" \\
org.label-schema.vendor="CentOS" \\
org.label-schema.license="GPLv2" \\
org.label-schema.build-date="20200114" \\
org.opencontainers.image.title="CentOS Base Image" \\
org.opencontainers.image.vendor="CentOS" \\
org.opencontainers.image.licenses="GPL-2.0-only" \\
org.opencontainers.image.created="2020-01-14 00:00:00-08:00"
# 启动命令
CMD ["/bin/bash"]
- 示例2:mysql
- https://github.com/docker-library/mysql/blob/bc6e37a2bed792b1c4fc6ab1ec3ce316e6a5f061/8.0/Dockerfile
# debian镜像
FROM debian:buster-slim
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
# 创建mysql的用户名、用户组
RUN groupadd -r mysql && useradd -r -g mysql mysql
# 执行apt-get命令安装相关依赖
RUN apt-get update && apt-get install -y --no-install-recommends gnupg dirmngr && rm -rf /var/lib/apt/lists/*
# add gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
# 设置版本信息
ENV GOSU_VERSION 1.12
# 安装相关软件
RUN set -eux; \\
savedAptMark="$(apt-mark showmanual)"; \\
apt-get update; \\
apt-get install -y --no-install-recommends ca-certificates wget; \\
rm -rf /var/lib/apt/lists/*; \\
dpkgArch="$(dpkg --print-architecture | awk -F- ' print $NF ')"; \\
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \\
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \\
export GNUPGHOME="$(mktemp -d)"; \\
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \\
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \\
gpgconf --kill all; \\
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \\
apt-mark auto '.*' > /dev/null; \\
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \\
chmod +x /usr/local/bin/gosu; \\
gosu --version; \\
gosu nobody true
# 执行创建文件夹目录
RUN mkdir /docker-entrypoint-initdb.d
# 安装mysql
RUN apt-get update && apt-get install -y --no-install-recommends \\
# for MYSQL_RANDOM_ROOT_PASSWORD
pwgen \\
# for mysql_ssl_rsa_setup
openssl \\
# FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db:
# File::Basename
# File::Copy
# Sys::Hostname
# Data::Dumper
perl \\
# install "xz-utils" for .sql.xz docker-entrypoint-initdb.d files
xz-utils \\
&& rm -rf /var/lib/apt/lists/*
RUN set -ex; \\
# gpg: key 5072E1F5: public key "MySQL Release Engineering <mysql-build@oss.oracle.com>" imported
key='A4A9406876FCBD3C456770C88C718D3B5072E1F5'; \\
export GNUPGHOME="$(mktemp -d)"; \\
gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \\
gpg --batch --export "$key" > /etc/apt/trusted.gpg.d/mysql.gpg; \\
gpgconf --kill all; \\
rm -rf "$GNUPGHOME"; \\
apt-key list > /dev/null
# 设置环境变量
ENV MYSQL_MAJOR 8.0
ENV MYSQL_VERSION 8.0.20-1debian10
RUN echo "deb http://repo.mysql.com/apt/debian/ buster mysql-$MYSQL_MAJOR" > /etc/apt/sources.list.d/mysql.list
# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql)
# also, we set debconf keys to make APT a little quieter
RUN \\
echo mysql-community-server mysql-community-server/data-dir select ''; \\
echo mysql-community-server mysql-community-server/root-pass password ''; \\
echo mysql-community-server mysql-community-server/re-root-pass password ''; \\
echo mysql-community-server mysql-community-server/remove-test-db select false; \\
| debconf-set-selections \\
&& apt-get update && apt-get install -y mysql-community-client="$MYSQL_VERSION" mysql-community-server-core="$MYSQL_VERSION" && rm -rf /var/lib/apt/lists/* \\
&& rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld \\
&& chown -R mysql:mysql /var/lib/mysql /var/run/mysqld \\
# ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
&& chmod 777 /var/run/mysqld
# 挂卷信息,防止数据丢失!!!!
VOLUME /var/lib/mysql
# Config files
# config配置
COPY config/ /etc/mysql/
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]
# 对外暴露的mysql端口
EXPOSE 3306 33060
CMD ["mysqld"]
延伸:
- 构建加速:从版本18.09开始,Docker支持由moby / buildkit 项目提供的用于执行构建的新后端
以上是关于docker学习Dockerfile写作的主要内容,如果未能解决你的问题,请参考以下文章
Docker学习笔记-- 如何使用Dockerfile构建镜像
Docker学习笔记-- 如何使用Dockerfile构建镜像