服务器docker部署_如何使用docker部署ktor服务器

服务器docker部署

We’ve seen already how to architecture a Ktor server application and how to test most important layers. Now it is time to see how we can approach server deployment using Docker.

我们已经了解了如何构建Ktor服务器应用程序以及如何测试最重要的层。 现在是时候看看我们如何使用Docker进行服务器部署了。

为什么选择Docker? (Why Docker?)

Docker is a technology (I think it is wider than a piece of software) that allows us to easily deploy applications. It is ranked #1 in “Most Loved” and #2 “Most Wanted” platform in the 2019 StackOverflow Survey, and makes surprisingly easy to run an instance of many popular applications (or any other you setup) using containers.

Docker是一项技术(我认为它比软件更广泛),使我们能够轻松部署应用程序。 在2019年StackOverflow调查中,它在“最受欢迎”平台中排名第一,在“最受欢迎”平台中排名第二,使用容器运行许多流行应用程序(或您设置的任何其他应用程序)的实例异常容易。

什么是容器? (What is a container?)

“A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.”

“容器是打包代码及其所有依赖项的软件的标准单元,因此该应用程序可以从一个计算环境快速可靠地运行到另一个计算环境。”

In other words, a container is an isolated piece of software you can pack up inside an image (container image, or Docker build output), ship that image to another computer and run it without any computing environment dependency.

换句话说,容器是一个独立的软件,您可以将其打包在一个映像(容器映像或Docker构建输出)中,将该映像运送到另一台计算机并在不依赖任何计算环境的情况下运行它。

我们正在构建Docker映像吗? (Are we building a Docker image?)

Yes! This is done using a Dockerfile file placed in our repository root folder and it will define how we are creating our Ktor Docker image. This file will include all needed commands to build our image, normally starting with a FROM command and optionally ending with CMD. In our case, I will only focus on the needed ones to build our Ktor image. You can see them in the following snippet:

是! 这是使用放置在存储库根文件夹中的Dockerfile文件完成的,它将定义我们如何创建Ktor Docker映像。 该文件将包含所有用于构建映像的命令,通常以FROM开头 命令,并以CMD结尾。 在我们的案例中,我将只关注构建Ktor图像所需的对象。 您可以在以下片段中看到它们:

# App Building phase --------
FROM openjdk:8 AS build


RUN mkdir /appbuild
COPY . /appbuild


WORKDIR /appbuild


RUN ./gradlew clean build
# End App Building phase --------


# Container setup --------
FROM openjdk:8-jre-alpine


# Creating user
ENV APPLICATION_USER 1033
RUN adduser -D -g '' $APPLICATION_USER


# Giving permissions
RUN mkdir /app
RUN mkdir /app/resources
RUN chown -R $APPLICATION_USER /app
RUN chmod -R 755 /app


# Setting user to use when running the image 
USER $APPLICATION_USER


# Copying needed files
COPY --from=build /appbuild/build/libs/KtorEasy*all.jar /app/KtorEasy.jar
COPY --from=build /appbuild/resources/ /app/resources/
WORKDIR /app


# Entrypoint definition
CMD ["sh", "-c", "java -server -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:InitialRAMFraction=2 -XX:MinRAMFraction=2 -XX:MaxRAMFraction=2 -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+UseStringDeduplication -jar KtorEasy.jar"]
# End Container setup --------

Building phase: as we are going to run a Java application, we start from openjdk container to build our sources running gradlew build command.

构建阶段:在运行Java应用程序时,我们从openjdk容器开始,运行gradlew build命令来构建源代码。

Container setup: once we have our app built, we can place it inside our container. We start from openjdk-jre image, as we are no longer building Java, just running it. We create a new user and declare it in the system, giving it permissions where needed and setting it to be used when running our container. It is just left copying our project files and defining container entrypoint (this point is specified in Ktor documentation). As you can see in line 29 from previous snippet, Docker container will contain a .jar file that we still cannot generate, so we need to configure how to pack our Java application inside this jar file.

容器设置:构建好应用程序后,可以将其放入容器中。 我们从openjdk-jre映像开始,因为我们不再构建Java,而只是运行它。 我们创建一个新用户并在系统中声明它,在需要的地方给它权限,并设置它在运行容器时使用。 只需复制我们的项目文件并定义容器入口点(此点在Ktor文档中指定)。 正如您从上一片段的第29行看到的那样,Docker容器将包含一个我们仍然无法生成的.jar文件,因此我们需要配置如何将Java应用程序打包到该jar文件中。

打包我们的应用程序 (Packaging up our application)

To deploy a Java application, we need to package it up. We can automate this process using Gradle and Shadow plugin. In the following snippet you can see how to install this plugin in your build.gradle file:

要部署Java应用程序,我们需要将其打包。 我们可以使用GradleShadow插件自动执行此过程。 在以下代码片段中,您可以看到如何在build.gradle文件中安装此插件:

buildscript {
    repositories {
        jcenter()   
    }
    
    dependencies {
        [...]
        classpath "com.github.jengelman.gradle.plugins:shadow:$shadowwar_version"
    }
}


apply plugin: 'kotlin'
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'


application {
    mainClassName = "com.batcuevasoft.ApplicationKt"
}


[...]


shadowJar {
    manifest {
        attributes 'Main-Class': mainClassName
    }
}


dependencies { [...] }

Note: new Ktor 1.4.0 documentation differs a bit how to do this step. If you find this setup is not working anymore, please review this documentation.

注意:新的Ktor 1.4.0文档在执行此步骤的方式上有所不同。 如果您发现此设置不再起作用,请查阅此文档

Once we have added Shadow, this jar file will be automatically generated inside build folder when building our app.

添加Shadow后,在构建应用程序时,该jar文件将在build文件夹内自动生成。

如何启动Ktor服务器 (How to launch Ktor server)

Now that we have our Dockerfile file in our repository's root folder, we can checkout our code where we want to deploy our server and build our backend image (Docker should be available there). To do this, we can use the following command:

现在我们已经在存储库的根文件夹中有了Dockerfile文件,我们可以在要部署服务器并构建后端映像的地方签出代码( Docker应该在那里可用)。 为此,我们可以使用以下命令:

docker build -f Dockerfile --no-cache -t ktoreasy .

Note: -f Dockerfile & --no-cache parameters can be omitted, but I prefer to use them to avoid problems while running this example.

注意: -f Dockerfile--no-cache参数可以省略,但我更喜欢使用它们以避免在运行此示例时出现问题。

Once this task ends, Docker will now have available ktoreasy container image and we can run it with the following command:

完成此任务后, Docker现在将具有可用的ktoreasy容器映像,我们可以使用以下命令运行它:

docker run --publish 3600:3500 --detach --name ktoreasy ktoreasy:latest

Hurraaayyyyy!!! 👏 👏 👏 👏 👏

Hurraaayyyyyy !!! 👏👏👏👏👏

Buuut…不起作用…🤔 (Buuut… it is not working… 🤔)

Don't panic, it is expected. You still need to connect to the database, and with the default application configuration environment (dev), it is expecting to find it inside Docker with "db" container name, as you can see in the following snippet:

不要惊慌,这是预料之中的。 您仍然需要连接到数据库,并且使用默认的应用程序配置环境( dev ),它期望在Docker内部使用“ db”容器名称找到它,如以下代码片段所示:

ktor {
    deployment {
            dev {
                host = "localhost"
                port = 3500
                databaseHost = "db"
                databasePort = "3306"
            }
            uat {
                host = "myhost.com"
                port = 3501
                databaseHost = "db"
                databasePort = "3306"
            }
            prod {
                host = "myhost.com"
                port = 3502
                databaseHost = "databasehost"
                databasePort = "3309"
            }
        }


        application {
            modules = [ com.batcuevasoft ]
        }
}

To run this example, you need to have a MySQL database called "ktoreasydb" running in databaseHost:databasePort. This is an interesting exercise to demonstrate how Docker works, as we have to change application configuration, that is already defined inside Docker image. To do this, we have to change our code (application.conf file) and make it point to our database, build Docker image as before and run it again.

要运行此示例,您需要在databaseHost:databasePort中运行一个名为“ ktoreasydb”MySQL数据库。 这是一个有趣的练习,展示了Docker如何工作,因为我们必须更改已在Docker映像中定义的应用程序配置。 为此,我们必须更改代码(application.conf文件),使其指向我们的数据库,像以前一样构建Docker映像,然后再次运行它。

Yeah, I'm also too lazy for doing that more than once...

是的,我也懒得不止一次地做那件事...

嗯,这不如预期的好… (Mmmm this is not as good as expected…)

You are right. Why is Docker such an amazing tool if we need to do this process? Actually, this way of working is not used when you have dependencies, like database instances. Defining a Docker Compose file will help to define and run all dependencies together. This file (docker-compose.yml) is already included in the Github repository:

你是对的。 如果我们需要执行此过程,为什么Docker如此出色呢? 实际上,当您具有依赖项(例如数据库实例)时,不会使用这种工作方式。 定义Docker Compose文件将有助于一起定义和运行所有依赖项。 该文件( docker-compose.yml )已包含在Github存储库中

version: '2.1'


# Services we are going to use when running
services:
  # Database instance we need to store data
  db:
    image: mariadb:latest
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=mypassword
      - MYSQL_DATABASE=ktoreasydb
      - MYSQL_USER=ktoreasyuser
      - MYSQL_PASSWORD=ktoreasypassword
    # Internal port 3306 should always match mariaDB working port
    ports:
      - "3308:3306"


# Backend instance that depends on database instance to start.
  backend:
    image: ktoreasy:latest
    mem_limit: 300m
    depends_on:
      - db
    environment:
      - ENVIRONMENT=dev
    restart: always
    # Internal port 3500 should always match your backend defined port
    ports:
      - "3510:3500"

Now you can just run in your project root folder:

现在,您可以在项目根文件夹中运行:

docker-compose up -d

Note: ports 3308 & 3510 should be available in the machine that will run this code.

注意:端口33083510在运行此代码的计算机中应该可用。

If you check your list of containers in Docker, you will see KtorEasy group with backend and database instances inside. Easy and elegant!

如果在Docker中检查容器列表,您将看到内部包含后端和数据库实例的KtorEasy组。 轻松优雅!

If you want to give it a try, clone the following Github repository and don’t be shy to leave a comment or a PR if you feel you can add something. Both are welcome!

如果您想尝试一下,请克隆下面的Github存储库,如果可以添加内容,请不要发表评论或PR。 两者都欢迎!

Have fun and happy “clean” coding!

享受快乐快乐的“干净”编码!

PS: You can claim this is not a real world example, but maybe in a future I can show how to approach microservices with on demand escalation using Kubernetes…

PS:您可以说这不是一个真实的例子,但是也许将来我可以展示如何使用Kubernetes通过按需升级来实现微服务…

翻译自: https://medium.com/swlh/how-to-deploy-a-ktor-server-using-docker-dd01f4883c30

服务器docker部署

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值