多阶段构建Docker镜像

首先

我最近開始學習Docker。
這次我要設置Spring Boot的開發環境。既然這樣,我也想稍微接觸一下Maven。
我的目標是能夠運行Spring Boot項目。

环境

    • macOS Mojave ver10.14.5

 

    Docker for Mac ver18.09.2

做好準備。

准备一个Spring Boot项目

スクリーンショット 2019-08-22 19.19.03.png
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>hello</groupId>
    <artifactId>hello-world</artifactId><!-- ここ -->
    <version>0.0.1</version><!-- ここ -->
    <name>hello</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

接下来,我们需要编辑HelloApplication.java文件,使其显示”Hello World from Docker”。

package hello.hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class HelloApplication {

    @RequestMapping("/")
    public String home() {
        return "Hello World from Docker";
    }

    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

我暂时先尝试着进行构建。

最终,我们将把它转化为Dockerfile,但由于经验不足,我们不能一下子就写出来,所以我们先尝试用从Maven镜像创建的容器来构建项目。
通过使用”-v”选项,容器内部也可以访问hello目录及其子目录。

docker run --rm -it -v /Users/.../hello:/opt/java maven:3.6.1-jdk-8 /bin/bash

一旦容器启动后,我们会执行命令进行构建。
Maven会开始工作,将jar文件输出到target目录中。

root@2a00dc872367:# cd /opt/java
root@2a00dc872367:/opt/java# mvn install
(省略)
[INFO] BUILD SUCCESS
(省略)
root@2a00dc872367:/opt/java# ls target
hello-world-0.0.1.jar (他にもファイルがあるが、省略)

那么,根据以上内容,我们来编写Dockerfile。

这个问题

Dockerfile的描述

1. 使用多阶段构建(Multi-Stage Build)来实现在容器中进行以下操作:
– 构建 Spring Boot 项目(生成 jar 文件)
2. 将 jar 文件复制到可执行容器中
3. 执行

# 1.jarファイルの生成
FROM maven:3.6.1-jdk-8 as builder
RUN mkdir -p /opt/java/src
  # 必要なソースを /opt/java へコピー
COPY ./hello/ /opt/java/
  # mvn install によりtargetディレクトリにjarが生成される
RUN cd /opt/java && mvn install

FROM openjdk:8-jre-alpine
RUN mkdir -p /opt/app/
# 2.builderコンテナの中にあるjarファイルを /opt/app/ にコピー
COPY --from=builder /opt/java/target/hello-world-0.0.1.jar /opt/app/
  # 8080ポートを開ける
EXPOSE 8080
# 3.アプリを実行
CMD  ["java","-jar","/opt/app/hello-world-0.0.1.jar"]

创建和启动容器

在下面的容器中创建并启动容器。

docker build -t java_server .
docker run --rm -it -p 8080:8080 java_server:latest -d
スクリーンショット 2019-08-23 11.56.33.png

最后

当你无法正确编写Dockerfile时,我认为一个好的方法是先创建和启动容器,然后将整个过程整理到Dockerfile中。

在中国,只需要一个选项,将以下内容用中文进行本地化改写如下:

参考 means “reference” in English.

使用Docker来开始Spring Boot
使用CodeBuild来进行Docker镜像的多阶段构建
尝试编写Dockerfile
总结Dockerfile中ADD和COPY的区别
常用的Maven命令集

更新 –

Dockerfile (中文:容器文件)

尽量写地图片更小。
如果只是复制本地文件,使用COPY命令比ADD命令更好。
尽量保持Dockerfile尽量短。

ADD ./hello/pom.xml /opt/java/
ADD ./hello/src /opt/java/src

COPY ./hello/ /opt/java/

用JDK的话,我一直不太确定,但如果只是执行的话,JRE就足够了。

FROM openjdk:jdk-alpine
FROM openjdk:8-jre-alpine

只需要jar文件才能启动,所以不需要完整复制目标目录。

COPY --from=builder /opt/java/target/ /opt/app/
COPY --from=builder /opt/java/target/hello-world-0.0.1.jar /opt/app/
bannerAds