dockerfile简介
- dockerfile 用于构建docker镜像
- dockerfile包含镜像构建所需要的指令
- dockerfile有固定的语法规则
dockerfile的构建
docker build -t TAG_NAME DOCKERFILE_DICT
dockerfile的基本结构
FROM ubuntu:21.04 # base image
RUN apt-get update # shell command
ADD file target_dict # file and target image dict
CMD ["python3", "/hello.py"] # command
dockerfile 基本语法
FROM
- 如何选择基础镜像 FROM [base image] ?
- Official First
- 固定版本而不是使用 latest 版本
- 尽量选择体积小的镜像
RUN
RUN COMMAND # 不使用多个RUN而使用 && \ 拼接
# 容器内部执行的命令
COPY & ADD
FROM base image
COPY hello.py /app/hello.py # 本地hello.py文件复制到docker镜像下的/app目录下
# ADD 复制并可自动解压
WORKDIR
WORKDIR 目录变更
相当于运行 cd
之后的COPY ADD等命令的默认路径即是WORKDIR指定地址
ARG & ENV
用来设置变量
ENV VERSION=2.0.1
ARG VERSION=2.0.1
RUN ${VERSION}
# ARG 变量只存在于镜像构建build时
# ENV 变量永久保存为环境变量
CMD
# 容器启动命令
CMD ['command','command']
# 如果定义了多个只执行最后一个
# 如果docker run时指定了其他命令,则CMD被忽略。
ENTRYPOINT
- CMD命令可以呗docker run参数覆盖,而ENTRYPOINT无法被覆盖,一定被执行。
- ENTRYPOINT & CMD可以联合使用,ENTRYPOINT设置执行的命令,CMD传递参数。
EXPOSE
EXPOSE [对外暴露端口 8080] # 声明开启了容器的哪些端口,更多的作用是给用户查看 只使用-p也可
配合 docker run -p 8080:8080 访问
EXPOSE & -p
https://stackoverflow.com/questions/22111060/what-is-the-difference-between-expose-and-publish-in-docker
dockerfile 最佳实践
-
合理使用缓存 : 将容易发生修改 ( 文件发生修改 导致不能使用CACHE ) 的Dockerfile语句放在较后的位置,提高缓存的利用(build时)。
-
使用 ‘.dockerignore’ 文件: (类似 .gitignore)忽略不需要的文件,减小镜像大小,加速构建。
-
多阶段构建: 适合需要依赖大量环境编译且最后运行不需要的过程。eg gcc,go,jdk&jre
FROM gcc:9.4 AS builder
COPY hello.c /src/hello.c
WORKDIR /srcRUN gcc --static -o hello hello.c # 在gcc镜像环境下编译
FROM alpine:3.13.5
COPY --from=builder /src/hello /src/hello # 将gcc环境下编译完成的可执行文件copy到alpine镜像下
ENTRYPOINT [ "/src/hello" ] # 执行
CMD []
- 使用非root用户构建镜像
-
使用root用户构建的镜像,普通用户可以使用docker进行 目录映射 来访问 本没有权限访问的文件。
-
甚至可以自己加sudo权限。
-
解决办法:
- 通过groupadd和useradd创建一个新的组和用户
- 通过 USER 指定命令要以新用户的身份运行
RUN groupadd -r GROUP_NAME && useradd -r -g GROUP_NAME USER_NAME && \ mkdir /src && \ chown -R GROUP_NAME:USER_NAME /srcUSER USER_NAME