Skip to content

Java 应用部署到 Docker

从采用最原始的做法手工部署,到集成 Maven 插件半自动部署,最终使用 Jenkins 流水线实现自动化部署。

最原始的做法:手工部署

最原始的做法一般为:

  1. 打 JAR 包

    sh
    $ mvn clean package
  2. 将 JAR 包上传到服务器(宿主机)

    sh
    $ ls
    deploy-docker-sample-0.0.1-SNAPSHOT.jar
  3. 编写 Dockerfile 文件:

    dockerfile
    FROM eclipse-temurin:17-jdk-alpine
    COPY deploy-docker-sample-0.0.1-SNAPSHOT.jar /app.jar
    ENTRYPOINT ["java", "-jar", "/app.jar"]
    EXPOSE 8080
  4. 在服务器上创建 Docker 镜像

    sh
    $ docker build -t localhost:5000/deploy-docker-sample:0.0.1-SNAPSHOT .
  5. 基于此镜像启动 Docker 容器

    sh
    $ docker run -d -p 8080:8080 --name deploy-docker-sample localhost:5000/deploy-docker-sample:0.0.1-SNAPSHOT

集成 Maven 插件:半自动部署

使用 dockerfile-maven-plugin

  1. Maven 项目集成 dockerfile-maven-plugin 插件

    xml
    <build>
    	<plugins>
    		<plugin>
    			<groupId>com.spotify</groupId>
    			<artifactId>dockerfile-maven-plugin</artifactId>
    			<version>1.4.13</version>
    			<executions>
    				<execution>
    				<id>default</id>
    				<goals>
    					<goal>build</goal>
    					<goal>push</goal>
    				</goals>
    				</execution>
    			</executions>
    			<configuration>
    				<repository>localhost:5000/${project.artifactId}</repository>
    				<tag>${project.version}</tag>
    				<buildArgs>
    					<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
    				</buildArgs>
    			</configuration>
    		</plugin>
    	</plugins>
    </build>
  2. 在项目下编写 Dockerfile 文件:

    dockerfile
    FROM eclipse-temurin:17-jdk-alpine
    ARG JAR_FILE
    COPY ${JAR_FILE} /app.jar
    ENTRYPOINT ["java", "-jar", "/app.jar"]
    EXPOSE 8080
  3. 将项目提交到 Git 或 SVN

  4. 拉取项目到服务器本地

  5. 运行 Maven 打包命令

    sh
    $ mvn clean package
    ...
    [INFO] --- dockerfile-maven-plugin:1.4.13:build (default) @ deploy-docker-sample ---
    [INFO] dockerfile: null
    [INFO] contextDirectory: /home/ubuntu/maven-projects/deploy-docker-sample
    [INFO] Building Docker context /home/ubuntu/maven-projects/deploy-docker-sample
    [INFO] Path(dockerfile): null
    [INFO] Path(contextDirectory): /home/ubuntu/maven-projects/deploy-docker-sample
    [INFO] 
    [INFO] Image will be built as localhost:5000/deploy-docker-sample:0.0.1-SNAPSHOT
    [INFO] 
    [INFO] Step 1/5 : FROM eclipse-temurin:17-jdk-alpine
    [INFO] 
    [INFO] Pulling from library/eclipse-temurin
    [INFO] Digest: sha256:85c33b8a96bf36a5335adf754b45575df7df7935a84db560aa8ec16fd40dbf36
    [INFO] Status: Image is up to date for eclipse-temurin:17-jdk-alpine
    [INFO]  ---> 9db8c1f3019b
    [INFO] Step 2/5 : ARG JAR_FILE
    [INFO] 
    [INFO]  ---> Running in e94cb8ed8d94
    [INFO] Removing intermediate container e94cb8ed8d94
    [INFO]  ---> f03aae41fef2
    [INFO] Step 3/5 : COPY ${JAR_FILE} /app.jar
    [INFO] 
    [INFO]  ---> 5d31b418687b
    [INFO] Step 4/5 : ENTRYPOINT ["java", "-jar", "/app.jar"]
    [INFO] 
    [INFO]  ---> Running in e880c7a6c59d
    [INFO] Removing intermediate container e880c7a6c59d
    [INFO]  ---> c5deb2337484
    [INFO] Step 5/5 : EXPOSE 8080
    [INFO] 
    [INFO]  ---> Running in 1c2e28ada379
    [INFO] Removing intermediate container 1c2e28ada379
    [INFO]  ---> 9235644a9156
    [INFO] Successfully built 9235644a9156
    [INFO] Successfully tagged localhost:5000/deploy-docker-sample:0.0.1-SNAPSHOT
    [INFO] 
    [INFO] Detected build of image with id 9235644a9156
    [INFO] Building jar: /home/ubuntu/maven-projects/deploy-docker-sample/target/deploy-docker-sample-0.0.1-SNAPSHOT-docker-info.jar
    [INFO] Successfully built localhost:5000/deploy-docker-sample:0.0.1-SNAPSHOT
    ...
  6. 基于此镜像启动 Docker 容器

    sh
    $ docker run -d -p 8080:8080 --name deploy-docker-sample localhost:5000/deploy-docker-sample:0.0.1-SNAPSHOT

使用 Jenkins 流水线:自动化部署

集成 Maven 插件:半自动部署的基础上,使用 Jenkins 流水线实现自动化部署。

主要分为两步:自动打包为 Docker 镜像和自动启动 Docker 容器。

自动打包为 Docker 镜像

  1. 在项目下编写 Jenkinsfile 文件:
jenkinsfile
pipeline {
    agent {
        docker {
            image 'maven:3.8.6-eclipse-temurin-17-alpine'
            args '-v $HOME/.m2/:/root/.m2/'
        }
    }
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}
  1. Jenkins 创建一个流水线项目,指定项目 SCM 地址。具体使用,参见在源代码管理系统中定义流水线

  2. 构建流水线项目。构建成功后便得到了 Docker 镜像。

  3. 基于此镜像启动 Docker 容器

    sh
    $ docker run -d -p 8080:8080 --name deploy-docker-sample localhost:5000/deploy-docker-sample:0.0.1-SNAPSHOT

自动启动 Docker 容器

可以看到,上面第 4 步还是需要手动的。所以把这一步也加入流水线便可实现自动化部署。最新的 Jenkinsfile 文件内容如下:

jenkinsfile
pipeline {
    agent none
    stages {
        stage('Build') {
            agent {
                docker {
                    image 'maven:3.8.6-eclipse-temurin-17-alpine'
                    args '-v $HOME/.m2/:/root/.m2/'
                }
            }
            steps {
                sh 'mvn clean package'
            }
        }
        stage('Deploy') {
            agent any
            steps {
                sh 'docker run -d -p 8080:8080 --name deploy-docker-sample localhost:5000/deploy-docker-sample:0.0.1-SNAPSHOT'
            }
        }
    }
}

Released under the MIT License.