在容器化技术普及的今天,Docker 镜像已成为应用交付的标准格式。作为一名长期使用 Docker 的开发者,我深刻体会到定制化镜像的重要性。官方镜像往往无法满足企业特定的安全要求、性能优化和功能扩展需求,这就需要我们掌握镜像制作的技能。
制作 Docker 镜像主要基于以下实际需求:
这种方式适合偶尔需要制作的镜像,原理类似于给虚拟机打快照。具体步骤是:
bash复制docker run -it ubuntu:20.04 /bin/bash
bash复制apt update && apt install -y curl vim
bash复制docker commit -m "Added curl and vim" -a "Your Name" 容器ID 新镜像名:标签
实际案例:SpringBoot 应用镜像制作
bash复制docker run -it openjdk:8-jdk /bin/bash
bash复制docker cp app.jar 容器ID:/app/
bash复制java -jar /app/app.jar
bash复制docker commit -m "SpringBoot app" -a "Dev" 容器ID myapp:1.0
注意:快照方式会产生冗余数据,且无法版本化管理构建过程,不适合频繁构建的场景。
这是推荐的生产环境做法,通过文本文件定义构建步骤,具有可重复、可版本控制的优势。
基本命令:
bash复制docker build -t 镜像名:标签 .
dockerfile复制FROM ubuntu:20.04 AS builder
两种格式:
dockerfile复制RUN apt update && apt install -y git # shell格式
RUN ["/bin/bash", "-c", "echo hello"] # exec格式
最佳实践:
dockerfile复制COPY ./app /app # 只复制本地文件
ADD https://example.com/file.tar.gz /tmp # 可自动解压和下载
dockerfile复制ENTRYPOINT ["java", "-jar"]
CMD ["app.jar"]
区别:
dockerfile复制# 构建阶段
FROM maven:3.6 AS build
COPY . /app
RUN mvn package
# 运行阶段
FROM openjdk:8-jre
COPY --from=build /app/target/*.jar /app.jar
CMD ["java", "-jar", "/app.jar"]
优势:
使用.dockerignore文件
忽略不必要的文件,加速构建:
code复制.git
*.log
target/
优化缓存使用
镜像瘦身技巧
dockerfile复制RUN apt update && \
apt install -y package && \
rm -rf /var/lib/apt/lists/*
安全加固
dockerfile复制USER appuser
问题1:依赖下载超时
解决方案:
问题2:权限不足
解决方案:
问题:应用启动失败
排查步骤:
bash复制docker logs 容器ID
bash复制docker exec -it 容器ID /bin/bash
dockerfile复制ARG VERSION=latest
FROM base:$VERSION
构建时指定:
bash复制docker build --build-arg VERSION=1.0 .
dockerfile复制HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost/health || exit 1
使用工具检查安全漏洞:
bash复制docker scan 镜像名
dockerfile复制# 构建阶段
FROM maven:3.8.4-openjdk-11 AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 运行阶段
FROM openjdk:11-jre-slim
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
COPY --from=build /app/target/*.jar /app/app.jar
COPY --from=build /app/target/lib /app/lib
ENV JAVA_OPTS="-Xms512m -Xmx1024m"
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.jar"]
这个Dockerfile体现了以下最佳实践:
在实际项目中,我通过以下方法将Java应用镜像从780MB优化到150MB:
dockerfile复制FROM openjdk:11-jre-alpine
dockerfile复制RUN $JAVA_HOME/bin/jlink \
--add-modules java.base,java.logging \
--strip-debug \
--no-man-pages \
--no-header-files \
--compress=2 \
--output /opt/jre-minimal
dockerfile复制RUN strip -x /app/libs/*.so
这些优化使镜像部署速度提升5倍,同时减少了安全攻击面。
在CI/CD流水线中,我推荐以下实践:
bash复制docker build -t app:$(git rev-parse --short HEAD) .
bash复制DOCKER_BUILDKIT=1 docker build .
bash复制docker trust sign app:1.0
当遇到镜像构建问题时,我常用的调试方法:
bash复制docker build --target build -t app:build .
docker run -it app:build /bin/bash
bash复制docker build --no-cache --progress=plain .
bash复制docker history 镜像名
docker inspect 镜像名
这些技巧帮助我快速定位了90%的构建问题。
对于大型项目,我建议:
通过标准化镜像管理,我们团队将部署失败率降低了70%。