1、首先我们来谈一下,Dockerfile编写的大概步骤。
1) 手动编写Dockerfile的文件(注意就一个Dockerfile的文件没有后缀名),当然要满足Dockerfile的编写规范
2) 编写好这个文件之后,直接使用docker build命令执行,获得一个自定义镜像
3) docker run 运行定义好的docker镜像
我们再来谈一下什么是Dockerfile?
Dockerfile 就是用来构建Docker镜像的镜像文件,是由一系列命令和参数构成的脚本。
我们可以去docker的官方镜像中心查看相关镜像,如,查看centos镜像,如图:
点击查看Dockerfile ,如图:
发现它的基础镜像是FROM scratch ,那什么是scratch?
scratch是所有镜像的基础镜像(元镜像),相当于java中的Object
2、Dockerfile的基础内容:
1)每条保留字指令都必须为大写字母且后面要跟随至少一个参数
2)指令按照从上到下,顺序执行
3)#表示注释
4)每条指令都会创建一个新的镜像层,并对镜像进行提交
3、Doackerfile执行的流程:
1)docker从基础镜像运行一个容器
2)执行一条指令并对容器作出修改
3)执行类似docker commit的操作提交一个新的镜像层
4)执行dockerfile中的下一条指令直到所有指令都执行完成
4、Dockerfile中的保留字指令:
FROM 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER 镜像维护者的名称和邮箱
RUN 容器运行时需要执行的命令
EXPOSE 当前容器对外暴露出的端口号
WORKDIR 指定在创建容器后,终端默认登录的进来工作的目录,一个落脚点
ENV 用来构建镜像中设置环境变量
ADD 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY 类似ADD,拷贝文件和目录到镜像中。
将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置。如:COPY src dest COPY ["src" , "dest""]
VOLUME 容器数据卷,用于数据保存和持久化工作
CMD 指定一个容器启动时要运行的命令。Dockerfile 中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
ENTRYPOINT 指定一个容器启动时要运行的命令。ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数
ONBUILD 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发
FROM python:3.11.4
MAINTAINER haijin # 镜像作者信息
WORKDIR /app
# 工作目录,这个目录对应于镜像内的工作目录,后面的所有涉及到路径的操作都可以
# 使用WORKDIR的相对路径来指定
COPY requirements.txt requirements.txt
# 拷贝requirements.txt 到 镜像中/app/requirements.txt
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装pip包
COPY . .
# 将当前文件中的目录复制到/app目录下
ENV FLASK_APP app
# 设置环境变量,让flask run 命令能够找到启动文件的位置
EXPOSE 8386
ENTRYPOINT ["python"]
CMD ["app.py"]
# 执行启动命名 flask run -h 0.0.0.0 -p 8386 列表中的每个元素之间代表空格
# 使用Eclipse Temurin 17 JDK Alpine作为基础镜像
FROM eclipse-temurin:17-jdk-alpine
# 添加元数据标签
LABEL maintainer="your-email@example.com"
LABEL name="service-1"
LABEL version="1.0.0"
LABEL description="Service 1 - Spring Boot微服务"
LABEL org.opencontainers.image.title="service-1"
LABEL org.opencontainers.image.description="Service 1 - Spring Boot微服务"
LABEL org.opencontainers.image.version="1.0.0"
LABEL org.opencontainers.image.authors="your-email@example.com"
# 设置工作目录
WORKDIR /app
# 设置时区
ENV TZ=Asia/Shanghai
RUN apk add --no-cache tzdata && \
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
echo $TZ > /etc/timezone
# 安装curl用于健康检查
RUN apk add --no-cache curl
# 创建非root用户
RUN addgroup -g 1001 appuser && adduser -D -u 1001 -G appuser appuser
# 复制jar包到容器中
COPY service-1.jar app.jar
# 创建配置目录用于挂载ConfigMap
RUN mkdir -p /app/config && \
chmod 755 /app/config
# 修改文件所有者
RUN chown -R appuser:appuser /app
# 切换到非root用户
USER appuser
# 暴露端口
EXPOSE 9001
# 设置JVM参数和环境变量
ENV JAVA_OPTS="-Xms4g -Xmx4g -XX:+UseG1GC -XX:+UseContainerSupport"
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
CMD curl -f http://localhost:9001/actuator/health || exit 1
# 启动应用
# 优先使用挂载的配置文件,如果不存在则使用默认配置
ENTRYPOINT ["sh", "-c", "if [ -f /app/config/application.yml ]; then java $JAVA_OPTS -jar app.jar --spring.config.location=classpath:/application.yml,file:/app/config/application.yml; else java $JAVA_OPTS -jar app.jar; fi"]