为了让读者更好地理解多阶段Docker镜像构建,本文将分步骤对其进行详细的讲解,并提供两个示例来说明具体的实现过程。
什么是Docker多阶段构建
Docker多阶段构建是一种避免构建大型Docker镜像的有效策略,它允许您使用单个Dockerfile定义多个构建阶段,并且只有最终阶段的镜像才包含实际运行所需的内容。这种方法能够减小Docker镜像的规模,降低Docker镜像的构建时间,同时还能保持代码的高度可维护性。
实现Docker多阶段构建的步骤
1. 编写Dockerfile
首先,你需要编写一个包含所有构建阶段的Dockerfile文件。Dockerfile文件中要包含每个构建阶段的指令,例如FROM
、RUN
和COPY
,以及一个COPY
指令将构建阶段所需的文件复制到相应的构建阶段中。
2. 分离构建阶段
在Dockerfile中,您需要使用多个FROM指令来分离构建阶段,通常是一个FROM指令表示一个构建阶段。每个构建阶段都包含一个完整的运行时环境,它可以使用前一个构建阶段生成的文件。
例如,下面的代码演示了一个将Java应用程序打包成Docker镜像的Dockerfile。其中第一个FROM指令表示构建阶段,它使用Maven构建Java应用程序;而第二个FROM指令表示生产环境阶段,它仅仅包含Java运行时环境。
# 构建阶段
FROM maven:3.6-jdk-11 AS build
WORKDIR /app
# 将本地文件夹中的docker-compose.yml复制到容器中的/app文件夹中
COPY ./src /app/src
COPY ./pom.xml /app
# 编译并打包应用
RUN mvn clean package -DskipTests
# 生产阶段
FROM openjdk:11-jre-slim-buster
WORKDIR /app
# 将构建阶段中编译的JAR文件复制到生产环境中
COPY --from=build /app/target/*.jar /app/app.jar
# 暴露容器的端口
EXPOSE 8080
# 启动应用
CMD ["java", "-jar", "/app/app.jar"]
3. 命名构建阶段
为了能够使用构建阶段的文件,你需要在每个构建阶段中使用一个标签来标识它们。碰巧,Dockerfile中的FROM指令可以为构建阶段创建标签。下面的例子展示了为构建阶段和生产阶段分别命名的两个标签。
FROM scratch AS test
COPY --from=build /app/target/test /app/test
FROM ubuntu:20.04 AS build
COPY --from=test /app/test /app/test
# 构建生产环境
FROM alpine:3.13
COPY --from=build /app/build /app/build
4. 清理构建阶段
最后,您需要完成构建阶段并从镜像中删除它们的文件,以便最终生产环境镜像大小更小,并且不包含不必要的文件。您可以使用--from=<stage-name>
参数将文件从前一个构建阶段复制到下一个构建阶段。
例如,下面的代码展示了如何将从构建阶段复制的文件复制到最终生产镜像中,并同时清理构建阶段。
# 构建阶段
FROM node:lts-alpine as build
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:stable-alpine
WORKDIR /usr/share/nginx/html
RUN rm -rf ./*
COPY --from=build /usr/src/app/dist .
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
示例一:编译打包Java应用
下面是一个简单的Java应用程序无库,它就只是一个输出 Hello World! 的程序。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
通过使用Docker多阶段构建,可以在生产环境中运行该应用程序的可执行文件,而不需要在生产环境中安装Java或Maven等工具。在这个示例中,构建阶段使用Maven来编译Java应用程序,并生成可执行文件;而生产阶段只需要Java运行时环境即可。
下面是该示例应用程序所需的Dockerfile:
# 构建阶段
FROM maven:3.6-jdk-11 AS build
WORKDIR /app
COPY ./hello-world.java /app
RUN javac hello-world.java
# 生产阶段
FROM openjdk:11-jre-slim-buster
WORKDIR /app
COPY --from=build /app/hello-world.class /app
CMD ["java", "hello-world"]
现在,执行命令 docker build -t hello-world .
来构建Docker镜像。执行完成后使用 docker run --rm hello-world
来运行该Docker镜像,你会看到输出 "Hello World!"。
示例二:构建一个Web应用
在这个示例中,我们将展示如何使用Docker多阶段构建来构建一个React应用程序。
首先,创建一个新的React应用程序:
npx create-react-app my-app
cd my-app
然后,使用下面的Dockerfile来构建该应用程序:
# 构建阶段
FROM node:lts-alpine as build
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:stable-alpine
WORKDIR /usr/share/nginx/html
RUN rm -rf ./*
COPY --from=build /usr/src/app/build .
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
现在,执行命令 docker build -t my-app .
来构建Docker镜像。执行完成后使用 docker run -p 80:80 --rm my-app
来运行该Docker镜像,你会看到该创建的React应用程序。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Docker多阶段镜像构建的实现 - Python技术站