显示导航

以 Docker 容器形式运行 Grails

了解如何以 Docker 容器形式发布 Grails 应用程序。

作者:伊万·洛佩兹

Grails 版本 3.3.2

1 培训

Grails 培训 - 由创建并积极维护 Grails 框架的人员开发和实施!

2 入门

Docker 已成为一种无需安装任何依赖项即可运行应用程序的绝佳方式。

在本指南中,您将编写一个 Grails 应用程序,该应用程序将打包为 Docker 镜像,并在 Docker 容器中运行。

2.1 如何完成指南

要开始,请执行以下操作

Grails 指南存储库包含两个文件夹

  • initial 初始项目。通常是一个简单的 Grails 应用程序,其中增加了一些代码,以便于你快速上手。

  • complete 完成的示例。这是按照指南所述的步骤进行操作并对 initial 文件夹应用这些更改的结果。

要完成指南,请转到 initial 文件夹

  • cd 更改为 grails-guides/grails-as-docker-container/initial

并按照下一部分中的说明进行操作。

如果您将 cd 更改为 grails-guides/grails-as-docker-container/complete,则可以直接转到完成的示例

3 撰写指南

3.1 安装并配置 Docker

如果你尚未安装 Docker,则需要 安装它

根据你所在的具体环境,可能需要将 Docker 可用内存增加到 4GB 或更多。

Docker Preferences

提示:获取 Kitematic

Kitematic 是一个优秀的管理 Docker 容器的桌面应用程序。您首次单击打开 Kitematic 时,它将提示您下载并安装它。然后您可以使用 Kitematic 查看容器的输出,管理它们的设置等。

Kitematic

3.2 Gradle Docker 插件

在本指南中,我们使用了 Gradle Docker 插件;一个用于管理 Docker 镜像和容器的 Gradle 插件。

要安装 Gradle 插件,请修改 build.gradle

build.gradle
buildscript {
    repositories {
        mavenLocal()
        maven { url "https://repo.grails.org/grails/core" }
    }
    dependencies {
        classpath "org.grails:grails-gradle-plugin:$grailsVersion"
        classpath "gradle.plugin.com.energizedwork.webdriver-binaries:webdriver-binaries-gradle-plugin:1.1"
        classpath "gradle.plugin.com.energizedwork:idea-gradle-plugins:1.4"
        classpath "org.grails.plugins:hibernate5:${gormVersion-".RELEASE"}"
        classpath "com.bertramlabs.plugins:asset-pipeline-gradle:2.14.6"
        classpath "com.bmuschko:gradle-docker-plugin:3.2.1" (1)
    }
}
apply plugin:"eclipse"
apply plugin:"idea"
//apply plugin:"war" (2)
apply plugin:"org.grails.grails-web"
apply plugin:"com.energizedwork.webdriver-binaries"
apply plugin:"com.energizedwork.idea-project-components"
apply plugin:"asset-pipeline"
apply plugin:"org.grails.grails-gsp"
apply plugin:"com.bmuschko.docker-remote-api" (1)
1 Gradle Docker 插件
2 移除 war 插件,因为我们将生成可运行的 jar

3.3 应用程序入口脚本

创建一个脚本,该脚本将作为容器的入口点。

src/main/docker/app-entrypoint.sh
#!/bin/sh
java -Djava.security.egd=file:/dev/./urandom -jar /app/application.jar

3.4 Gradle Docker 任务

配置多个 Gradle 任务,这些任务允许我们构建可运行的 jar,将其与所需的资源一起复制到一个临时目录,生成一个 Dockerfile 文件,最后构建 docker 镜像。

build.gradle
import com.bmuschko.gradle.docker.tasks.image.Dockerfile
import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage
...
..
.
ext {
    dockerTag = "grails-sample/${project.name}:${project.version}".toLowerCase() (1)
    dockerBuildDir = mkdir("${buildDir}/docker") (2)
}
task prepareDocker(type: Copy, dependsOn: assemble) { (3)
    description = 'Copy files from src/main/docker and application jar to Docker temporal build directory'
    group = 'Docker'

    from 'src/main/docker'
    from project.jar

    into dockerBuildDir
}
task createDockerfile(type: Dockerfile, dependsOn: prepareDocker) { (4)
    description = 'Create a Dockerfile file'
    group = 'Docker'

    destFile = project.file("${dockerBuildDir}/Dockerfile")

    from 'openjdk:8u151-jdk-alpine'
    maintainer 'John Doe "[email protected]"'

    exposePort 8080

    workingDir '/app'

    copyFile jar.archiveName, 'application.jar'
    copyFile 'app-entrypoint.sh', 'app-entrypoint.sh' (5)
    runCommand 'chmod +x app-entrypoint.sh'

    entryPoint '/app/app-entrypoint.sh' (5)
}
task buildImage(type: DockerBuildImage, dependsOn: createDockerfile) { (6)
    description = 'Create Docker image to run the Grails application'
    group = 'Docker'

    inputDir = file(dockerBuildDir)
    tag = dockerTag
}
1 定义 docker 镜像名称。它将类似于 grails-sample/myProject:0.1
2 用于构建 Docker 镜像的临时目录
3 将 src/main/docker 中的可运行 jar 文件和附加文件复制到临时目录
4 创建 Dockerfile 文件
5 复制 app-entrypoint.sh 脚本并将其定义为容器的入口点
6 构建 Docker 镜像

app-entrypoint.sh 的内容是

src/main/docker/app-entrypoint.sh
#!/bin/sh
java -Djava.security.egd=file:/dev/./urandom -jar /app/application.jar

4 构建应用程序

在创建新的 Gradle 任务后,我们现在可以执行

./gradlew buildImage

...
...
:complete:jar
:complete:bootRepackage
:complete:assemble (1)
:complete:prepareDocker
:complete:createDockerfile
:complete:buildImage (2)
Building image using context '/home/ivan/workspaces/oci/guides/grails-as-docker-container/complete/build/docker'.
Using tag 'grails-sample/complete:0.1' for image.
Step 1/8 : FROM openjdk:8u151-jdk-alpine
---> 3642e636096d
Step 2/8 : MAINTAINER John Doe "[email protected]"
---> Using cache
---> 3e1c67b067e8
Step 3/8 : EXPOSE 8080
---> Using cache
---> 144aadd0580e
Step 4/8 : WORKDIR /app
---> Using cache
---> c9af01e696f8
Step 5/8 : COPY complete-0.1.jar application.jar
---> e4f41e8f0840
Removing intermediate container 6dccf4039811
Step 6/8 : COPY app-entrypoint.sh app-entrypoint.sh
---> 0be562313720
Removing intermediate container 595d0cb7b9d2
Step 7/8 : RUN chmod +x app-entrypoint.sh
---> Running in 3b41eb944045
---> 5f6fa6b0ab9a
Removing intermediate container 3b41eb944045
Step 8/8 : ENTRYPOINT /app/app-entrypoint.sh
---> Running in 3221a85ae904
---> 68f5588d1134
Removing intermediate container 3221a85ae904
Successfully built 68f5588d1134
Successfully tagged grails-sample/complete:0.1 (3)
Created image with ID '68f5588d1134'.

BUILD SUCCESSFUL

Total time: 11.453 secs
1 在 assemble 任务后,将执行新的 docker 任务
2 使用在上一个任务中中生成的 Dockerfile 构建镜像。显示 docker 命令的输出
3 已创建镜像 grails-sample/complete:0.1
$ docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
grails-sample/complete         0.1                 68f5588d1134        3 minutes ago       143MB

运行应用程序

运行已 docker 化的 Grails 应用程序就像这么简单

$ docker run -p 8080:8080 grails-sample/complete:0.1

几秒钟后,我们将看到消息 Grails 应用程序在 http://localhost:8080 处使用环境:production 运行

5 仅使用 Docker

或者,您可以手动创建一个 Docker 文件。

  • 删除 Gradle 任务 createDockerfile 和 buildImage。

  • 移除对 Gradle Docker 插件的依赖

  • 移除 src/main/docker/app-entrypoint.sh。我们在 Dockerfile 中直接定义 CMD。

  • 创建文件 src/main/docker/Dockerfile

src/main/docker/Dockerfile
FROM openjdk:8u151-jdk-alpine
MAINTAINER John Doe "[email protected]"

EXPOSE 8080

WORKDIR /app
COPY *.jar application.jar

CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/application.jar"]

由于我们已经创建了 src/main/docker 目录下的 Dockerfile,所以 Gradle 任务 prepareDocker 会将其与应用程序可运行的 jar 一起复制。

创建镜像

$ ./gradlew prepareDocker
$ docker build --tag="grails-sample/complete:0.1" build/docker/

手动创建 Dockerfile 会将 Docker 镜像生成与 Docker Gradle 插件分离。

6 Grails 帮助

对象计算公司 (OCI) 赞助了本指南的创建。提供各种咨询和支持服务。

OCI 是 Grails 的家

认识团队