构建Docker镜像

构建Docker镜像的4种方式

Posted by LANY on December 12, 2019

构建Docker镜像的4种方式

(一)通过Dockerfile对项目的fat jar进行构建

  • 创建一个spring-boot项目

为了方便,你可以clone现有的项目来进行练习:

git clone https://github.com/spring-guides/gs-spring-boot-docker.git
cd gs-spring-boot-docker/initial

然后在项目中的src/main/java/hello/Application.java中添加一些简单的功能代码:

package 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 Application {

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

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

}

然后打包项目并启动

./mvnw package && java -jar target/gs-spring-boot-docker-0.1.0.jar
  • 容器化项目

在项目的根目录中创建Dockerfile,并添加如下构建代码:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

然后通过Dockerfile来进行镜像构建:

docker build -t lany/gs-spring-boot-docker .
  • 启动容器

当镜像构建完成之后,我们可以通过docker images镜像来查看已经制作好的镜像,名称为lany/gs-spring-boot-docker

现在我们在终端输入以下命令来启动该镜像:

docker run -p 8080:8080 -t lany/gs-spring-boot-docker

访问该项目的接口:

curl -i -XGET 'localhost:8080'

(二) 通过Dockerfile对项目的依赖项以及应用资源进行构建

  • 打包项目并对jar包进行资源分离

为了利用Spring Boot fat jar文件中依赖项和应用程序资源的清晰分离,我们可以将依赖项和应用程序打包并构建成镜像。

打包之前的步骤,参考第一章节的创建一个spring-boot项目

当项目打包完成之后,我们对打包完成的jar包进行分离:

mkdir -p target/dependency && (cd target/dependency;jar -xf ../../target/*.jar)

上一步的命令是在target目录中创建dependency文件夹,然后将分离之后的内容存放到dependency文件夹。

  • 将分离后的资源容器化

在项目的根目录创建Dockerfile文件,并添加如下内容:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=target/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]

然后通过docker build命令构建镜像:

docker build -t "lany/gs-spring-demo:latest" .
  • 启动容器

当镜像构建完成之后,我们可以通过docker images镜像来查看已经制作好的镜像,名称为lany/gs-spring-boot-docker

现在我们在终端输入以下命令来启动该镜像:

docker run -p 8080:8080 -t lany/gs-spring-boot-docker

访问该项目的接口:

curl -i -XGET 'localhost:8080'

(三) 根据docker-maven-plugin插件来构建docker镜像(免Dockerfile)

除了利用Dockerfile来构建镜像之外,如果你是用maven来构建项目,那么我们还可以用docker-maven-plugin在pom文件中来构建项目镜像。

  • 在pom中添加docker-maven-plugin插件依赖
<build>
  <plugins>
    <plugin>
      <groupId>com.spotify</groupId>
      <artifactId>docker-maven-plugin</artifactId>
      <version>1.2.0</version>
      <configuration>
        <imageName>lany/gs-spring-boot-docker</imageName>
        <baseImage>openjdk:8-jdk-alpine</baseImage>
        <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
        <!-- copy the service's jar file from target into the root directory of the image --> 
        <resources>
           <resource>
             <targetPath>/</targetPath>
             <directory>${project.build.directory}</directory>
             <include>${project.build.finalName}.jar</include>
           </resource>
        </resources>
      </configuration>
    </plugin>
  </plugins>
  <finalName>${project.artifactId}</finalName>
</build>

其中configuration节点的属性在这里解释以下:

imageName:镜像名
imageTags:配置镜像tag,这里指定了两个tag(最新的版本号和latest)
forceTags:强制在每次新的构建上覆盖镜像tags
baseImage:基础镜像
env:配置环境变量
entryPoint:配置执行命令
resources:配置目标jar包的位置
  • 构建运行

如果有私有仓库,可以先通过docker login登陆到私有仓库,这样以后就不需要一直登陆了,为上传镜像做准备。

1.指定maven命令进行打包

mvn clean package docker:build

上面这个命令做了打包以及构建镜像的动作。

2.运行容器

当项目镜像构建好了之后,我们可以通过docker run来启动容器:

docker run -p 8080:8080 -t --name dockerbuild lany/gs-spring-boot-docker:latest

访问项目接口:

curl -i -XGET 'localhost:8080'

在pom文件中可以直接指定baseimageentrypointcmdmaintainer以及resource而不需要单独的Dockerfile。 如果你需要在镜像中指定挂载点(volume)(或者其他docker-maven-plugin不支持的Dockerfile命令),你需要创建一个Dockerfile,并通过dockerDirectory指定Dockerfile文件的所在目录。

(四) 根据docker-maven-plugin插件来构建docker镜像

在上一章节中我们知道可以通过docker-maven-plugin插件免Dockerfile来构建镜像,好处就是可以直接在pom.xml中指定构建命令,确定就是不能支持更多的Dockerfile命令。我们这一章节就来通过docker-maven-plugin插件以及Dockerfile来构建镜像:

  • 在pom中添加docker-maven-plugin插件依赖

1.在项目根目录下创建dockerDir目录,并将Dockerfile添加到该目录下

2.在pom.xml文件中添加docker-maven-plugin插件依赖

<build>
  <plugins>
    <plugin>
      <groupId>com.spotify</groupId>
      <artifactId>docker-maven-plugin</artifactId>
      <version>1.2.0</version>
      <configuration>
        <imageName>lany/gs-spring-boot-docker</imageName>
        <imageTags>
            <imageTag>${project.version}</imageTag>
        </imageTags>
        <dockerDirectory>./dockerDir</dockerDirectory>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
      </configuration>
    </plugin>
  </plugins>
  <finalName>${project.artifactId}</finalName>
</build>

3.在Dockerfile文件中添加如下构建命令

FROM openjdk:8-jdk-alpine
VOLUME /tmp
EXPOSE 8080
ARG JAR_FILE=*.jar
ENV JAVA_OPTS -Xms256m -Xmx256m
ADD ${JAR_FILE} /app.jar
ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom /app.jar"]
  • 构建并运行

1.指定maven命令进行打包

mvn clean package docker:build

上面这个命令做了打包以及构建镜像的动作。

2.运行容器

当项目镜像构建好了之后,我们可以通过docker run来启动容器:

docker run -p 8080:8080 -t --name dockerbuild lany/gs-spring-boot-docker:latest

访问项目接口:

curl -i -XGET 'localhost:8080'

(五) 通过dockerfile-maven-plugin插件来构建docker镜像

官方推荐使用dockerfile-maven-plugin来构建docker镜像。

需要注意的是使用该插件构建镜像的要求:

  • java7及以后
  • maven3及以上(dockerfile-maven-plugin<=1.4.6 需要maven >=3 ,其他版本需要maven >=3.5.2)

  • 在项目根目录中添加Dockerfile文件,并在Dockerfile文件中添加如下内容:
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ENV JAVA_OPTS -Xms256m -Xmx256m
ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom /app.jar"]
ARG JAR_FILE
ADD ${JAR_FILE} /app.jar
  • 在pom文件中添加docker-file-maven依赖
<build>
  <plugins>
     <plugin>
        <groupId>com.spotify</groupId>
        <artifactId>dockerfile-maven-plugin</artifactId>
        <executions>
            <execution>
                <id>default</id>
                <goals>
                    <goal>build</goal>
                    <goal>push</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <repository>library/spring-demo</repository>
            <tag>${project.version}</tag>
            <buildArgs>
                <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
            </buildArgs>
        </configuration>
    </plugin>
  </plugins>
  <finalName>${project.artifactId}</finalName>
</build>
  • 构建镜像并运行

1.在这里我们可以省去mvn clean package docker:build这样繁琐的命令,可以直接用mvn clean package来进行打包并构建镜像。

2.运行容器

当项目镜像构建好了之后,我们可以通过docker run来启动容器:

docker run -p 8080:8080 -t --name dockerbuild spring-demo:0.1.0

访问项目接口:

curl -i -XGET 'localhost:8080'

详细文章请参考dockerfile-maven