Dockerfile常用指令
dockerfile概述

dockerfile常用指令
https://blog.51cto.com/u_12020737/4539268

| 指令 | 说明 |
|---|---|
| FROM | 指明当前的镜像基于哪个镜像构建 |
| LABEL | 标记镜像信息,添加元数据 |
| ARG | 定义构建镜像过程中使用的变量 |
| ENV | 指定环境变量 |
| VOLUME | 创建一个数据卷挂载点 |
| USER | 指定运行容器时的用户名或 UID |
| WORKDIR | 配置工作目录 |
| EXPOSE | 容器运行时的端口,默认是TCP |
| ADD | 从本地或URL添加文件或压缩包到镜像中,并自动解压 |
| COPY | 拷贝文件或目录到镜像中 |
| ONBUILD | 创建子镜像时指定自动执行的操作指令 |
| STOPSIGNAL | 指定退出的信号值 |
| HEALTHCHECK | 配置启动容器如何进行健康检查 |
| SHELL | 指定默认 shell 类型 |
| RUN | 构建镜像时运行的指定命令 |
| CMD | 运行容器时默认执行的命令,如果有多个CMD质量,最后一个生效。 |
| ENTRYPOINT | 指定镜像的默认入口命令 |


MAINTAINER参数已经弃用,用LABEL Author(作者名)="网站"替代。

ARG和ENV指定变量
https://www.jdon.com/58758.html
- ARG 定义
构建镜像过程中使用的变量,RUN可以使用ARG变量,CMD和ENTRYPOINT不能使用ARG变量 - ENV 指定
容器运行时使用的变量,ARG指定的变量不会容器运行时生效

# ENV示例:
# ENV <key1>=<value1> <key2>=<value2>...
ENV VERSION=1.0 DEBUG=on \
NAME="Happy Feet"
USER指定用户运行
注意:用户需事先建立好,否则无法切换
https://www.hi-linux.com/posts/44367.html
# 创建redis用户和redis组
RUN groupadd -r redis && useradd -r -g redis redis
以指定用户和组运行
# 指定用户和组
USER <user>[:<group>]
# 或
USER <UID>[:<GID>]
# 切换到redis用户运行
USER redis:redis
# 或
USER 1000:1000
WORKDIR设置工作目录
# 设置工作目录--相当于cd到/app目录
## 没有这个目录会自动创建
WORKDIR /app
EXPOSE暴露端口
默认是TCP协议,如果要暴露UDP端口,需要单独添加
# 同时在 TCP、UDP 上暴露端口
EXPOSE 80/tcp
EXPOSE 80/udp
# 暴露端口段
EXPOSE 443-26000
EXPOSE 443-26000/udp
ADD和COPY有什么区别
COPY: 把本地文件复制到容器;ADD:COPY的加强版,可以从url复制文件,并自动解压.- 如果 <源路径> 为一个
tar压缩文件的话,压缩格式为gzip,bzip2以及xz的情况下,ADD指令将会自动解压缩这个压缩文件到 <目标路径> 去。 URL下载和自动解压特性不能一起使用。任何压缩文件通过URL拷贝,都不会自动解压。
- 如果 <源路径> 为一个
# 将unzip阶段的的gost可执行程序复制到当前目录
COPY --from=unzip gost .
RUN,CMD,ENTRYPOINT的区别
RUN命令执行命令并创建新的镜像层,通常用于安装软件包CMD命令设置容器启动后默认执行的命令及其参数,但CMD设置的命令能够被docker run命令后面的命令行参数替换ENTRYPOINT配置容器启动时的执行命令(不会被忽略,一定会被执行,即使运行 docker run时指定了其他命令)
ENTRYPOINT非json则已ENTRYPOINT为准,如果ENTRYPOINT和CMD都是json,则ENTRYPOINT+CMD拼接成shell

docker run覆盖entrypoint
docker run覆盖entrypoint默认启动命令的方法,需要在run命令 添加 --entrypoint 参数。
## --entrypoint 覆盖 entrypoint 命令
sudo docker run -it --entrypoint /bin/bash [docker_image]
cmd和ENTRYPOINT并存
cmd和ENTRYPOINT并存时,cmd会成为ENTRYPOINT的参数,但是cmd命令必须有方括号,

没有写方括号,启动命令会自动补一个/bin/sh命令

ONBUILD子镜像指令
ONBUILD是一个特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行;
只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会执行ONBUILD后面的指令。
Dockerfile中的其它指令都是为了定制当前镜像而准备的,唯有ONBUILD是为了帮助别人定制自己而准备的.
比如: 当别人FROM你的镜像制作子镜像时, 执行rm -rf /*

AS阶段构建指令
https://blog.51cto.com/u_12020737/4539269
一个 dockerfile 可以有多个 FROM来创建多个镜像,或区分构建阶段,将一构建阶段作为二构建阶段的依赖项;
AS <阶段名> 就是命名当前构建阶段;
在后续构建阶段,可以给 FROM、COPY 指令用上,通过 --from=<上一个阶段名> 引用上一阶段构建的镜像.
例如:
1阶段编译好二进制文件;
2阶段COPY编译好的二进制文件;2阶段构建的容器会很小.
分阶段构建镜像,可以有效减小镜像.
# 阶段1,解压gost压缩包
## 请勿使用latest标签
FROM alpine:latest as unzip
# 设置gost版本号
ARG GOST_VERSION=3.0.0-rc8
# 下载GOST3压缩包
ADD https://github.com/go-gost/gost/releases/download/v"${GOST_VERSION}"/gost_"${GOST_VERSION}"_linux_amd64.tar.gz .
# 解压gost压缩包
RUN tar xvf gost_${GOST_VERSION}_linux_amd64.tar.gz
# 阶段2,复制gost可执行程序
FROM alpine:latest as copy_gost_bin
# 作者信息
LABEL qiaofei.li="https://blog.youkuaiyun.com/omaidb"
# 设置工作目录
WORKDIR /app
# 将unzip阶段的的gost可执行程序复制到当前目录
COPY --from=unzip gost .
# 将本地的配置文件复制到当前目录
COPY gost.yaml .
# USER <用户名>[:<用户组>]
# USER nobody:nobody
# 容器使用的端口
# EXPOSE 1080/tcp
# EXPOSE 1080/udp
# 运行主程序--指定绝对路径
ENTRYPOINT /app/gost -C gost.yaml
构建镜像
# 构建镜像
docker build -t gost .
# 修改tag
docker tag gost:latest omaidb/gost:latest
# 推送到仓库
docker push omaidb/gost:latest
HEALTHCHECK健康检查指令
https://blog.51cto.com/u_12020737/4539257
编辑dockerfile
建议使用VScode安装docker插件,能提供部分自动补全。

# 创建nginx项目目录
mkdir -p nginx
# 创建dockerfile文件
## dockerfiles的默认名称:dockerfile和Dockerfile
vim nginx/Dockerfile
Dockerfile设置时区
/etc/localtime是用来描述本机时间,而 /etc/timezone是用来描述本机所属的时区
# 设置上海时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
变量ENV和.dockerignore忽略文件
参考: https://www.yafa.moe/post/cka-docker-basic/
例如: ,执行COPY * .时,将排除文件写在.dockerignore中.
# 忽略文件
.dockerignore

示例:构建nginx镜像
# 基于redhat8镜像构建新镜像
## 请勿使用latest标签
#FROM redhat/ubi8:8.7-1090
## --platform 指定镜像的cpu架构
FROM --platform=linux/amd64 oraclelinux:8.10 as build
# 构建镜像时运行的命令
RUN yum makecache --nogpgcheck && \
yum install -y wget gcc make \
pcre pcre-devel zlib zlib-devel \
openssl openssl-devel
# 设置软件的版本号为变量
ENV VERSION=1.24.0
# 解压并拷贝文件到镜像
## add --是copy的加强版,可以从url复制文件
ADD https://nginx.org/download/nginx-${VERSION}.tar.gz .
# 解压nginx源代码
RUN tar -zxvf nginx-${VERSION}.tar.gz && \
# 构建镜像时运行的命令,编译安装nginx
cd nginx-${VERSION} && \
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_v2_module \
--with-http_stub_status_module \
--with-threads && \
make -j && make install
# 第2阶段
FROM oraclelinux:8.10
# 标签:作者信息
LABEL qiaofei.li="https://blog.csdn.com/omaidb"
# 设置工作目录
WORKDIR /usr/local/nginx
# 将build阶段的的nginx主程序程序复制到当前目录
COPY --from=build /usr/local/nginx /usr/local/nginx
RUN mkdir -p /usr/local/nginx/conf/vhost && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 设置环境变量
ENV PATH $PATH:/usr/local/nginx/sbin
# 容器使用的端口
# 默认是tcp
EXPOSE 80
EXPOSE 443
# 如果要开放udp,需要单独加
EXPOSE 80/udp
EXPOSE 443/udp
# 容器运行的命令,Nginx守护进程的固定格式
ENTRYPOINT ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
docker build-构建nignx镜像
Dockerfile文件的名称没有任何扩展名,一般默认是大写D和小写f.
dockerfiles的默认名称:dockerfile和Dockerfile. 如果文件名中有其他大写字母,它很可能会失败。

如果你不需要使用buildkit,在执行构建Dockerfile之前禁用。
export DOCKER_BUILDKIT=0
export COMPOSE_DOCKER_CLI_BUILD=0
https://stackoverflow.com/questions/64985913/failed-to-solve-with-frontend-dockerfile
# 在dockerfile同目录下执行build命令
## -f dockerfile文件可以是任何后缀名
## -t 构建出的镜像名:标签
## .表示dockerfile文件在当前目录下
docker build -f ./path/to/Dockerfile -t my-image .
# 构建一个针对 arm64 平台的镜像,并指定基础镜像
docker build --platform linux/arm64 -f Dockerfile.arm64 -t nginx-arm64:v1.
构建多cpu平台容器—未经测试
buildx需要单独安装,buildx项目地址:https://github.com/docker/buildx
Docker Buildx: 建议使用 Docker Buildx 来进行多平台构建,它提供了更强大的功能和更好的用户体验。
基础镜像: 确保你选择的基础镜像支持你目标的平台。
Dockerfile: 如果你的 Dockerfile 中有针对不同平台的特殊配置,可以考虑使用构建参数或者多阶段构建来实现。
# 构建一个针对 amd64 和 arm64 平台的镜像
docker buildx build --platform linux/amd64,linux/arm64 -f Dockerfile -t nginx-arm64-amd64:v1 .
下一代构建工具BuildKit
BuildKit也是非常好的dockfile构建工具
项目地址: https://github.com/moby/buildkit
dockerfile优化
将Docker镜像体积减小99%: https://juejin.cn/post/6844904101348638734
构建镜像Dockerfile文件优化:
减少镜像层: 一次RUN指令形成新的一层,尽量Shell命令都写在一行,减少镜像层。清理无用文件: 清理对应的残留数据,例如yum缓存。清理无用的软件包: 基础镜像默认会带一些debug工具,可以删除掉,仅保留应用程序所需软件,防止黑客利用。选择最小的基础镜像: 例如alpine使用非root用户运行:USER指令指定普通用户,降低权限- 使用
scratch镜像(空镜像)运行go程序
空镜像运行go程序
go语言的程序可以在scratch镜像(空镜像)中运行,非常的小,因为go是静态编译的二进制文件,运行时不依赖任何动态链接库。
# 指定空镜像
FROM scratch
为什么容器体积越小越好?
在K8S中可以快速的拉取容器,让pod漂移更快。
查看镜像层
分析镜像构建 https://blog.youkuaiyun.com/omaidb/article/details/122044116
# 查看nginx镜像的文件层
## --no-trunc : 禁止截断输出内容(显示完整的命令和层信息)
docker history omaidb/gost:3.0.0-rc6 --no-trunc


build常见错误
ERROR: failed to solve: failed to read dockerfile: open /var/lib/docker/tmp/buildkit-mount2237603866/Dockerfile: no such file or directory

原因:dockerfile名称不对。
将dockerfile文件重命名为Dockerfile
972

被折叠的 条评论
为什么被折叠?



