运行 docker 带有 Postgresql 数据库的容器中的简单 Kotlin Ktor 应用程序

Running simple Kotlin Ktor app in docker container with PostgresSql database

我想创建使用 PostgresSqlKotlin Ktor 的简单 Kotlin 应用程序,所有内容都应嵌入到 docker 容器中.

到目前为止,我成功地 运行 PostgresSqlPgAdmin 成功地相互连接并且我创建了 docker-compose.yml 文件,对我来说效果很好。当我想向它添加我的 Kotlin 应用程序时,问题就开始了。

这是我的 docker-compose.yml 文件


version: "3.9"
networks:
  m8network:
    ipam:
      config:
        - subnet: 172.20.0.0/24
services:
  postgres:
    image: postgres
    environment:
      - "POSTGRES_USER=SomeFancyUser"
      - "POSTGRES_PASSWORD=pwd"
      - "POSTGRES_DB=MSC8"
    ports:
      - "5432:5432"
    volumes:
      #           - postgres-data:/var/lib/postgresql/data
      - D:\docker\myApp\data:/var/lib/postgresql/data
    networks:
      m8network:
        ipv4_address: 172.20.0.6
  pgadmin:
    image: dpage/pgadmin4
    depends_on:
      - postgres
    environment:
      - "PGADMIN_DEFAULT_EMAIL=SomeFancyUser@domain.com"
      - "PGADMIN_DEFAULT_PASSWORD=pwd"
    #           - "PGADMIN_ENABLE_TLS=False"
    ports:
      - "5001:80"
    networks:
      m8network:
  app:
    build: .
    ports:
      - "5000:8080"
    links:
      - postgres
    depends_on:
      - postgres
    restart: on-failure
    networks:
      m8network:
#volumes:
#    postgres-data:
#        driver: local

这是我的应用程序源代码。


package com.something.m8

import com.squareup.sqldelight.db.SqlDriver
import com.squareup.sqldelight.sqlite.driver.asJdbcDriver
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import io.ktor.application.*
import io.ktor.html.*
import io.ktor.http.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import kotlinx.html.*
import java.io.PrintWriter
import java.util.*


fun HTML.index() {
    head {
        title("Hello from Ktor!")
    }
    body {
        div {
            +"Hello from Ktor"
        }
    }
}

fun main() {
    println("starting app")
    val props = Properties()
    props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource")
    props.setProperty("dataSource.user", "SomeFancyUser")
    props.setProperty("dataSource.password", "pwd")
    props.setProperty("dataSource.databaseName", "M8")
    props.setProperty("dataSource.portNumber", "5432")
    props.setProperty("dataSource.serverName", "172.20.0.6")
    props["dataSource.logWriter"] = PrintWriter(System.out)
    println("a")
    val config = HikariConfig(props)
    println("b")

    val ds = HikariDataSource(config)
    println("c")
    val driver: SqlDriver = ds.asJdbcDriver()
    println("d")
    MSC8.Schema.create(driver)
    println("e")
    embeddedServer(Netty, port = 8080,
       // host = "127.0.0.1"
    ) {
        routing {
            get("/") {
                call.respondHtml(HttpStatusCode.OK, HTML::index)
            }
            get("/m8/{code}") {
                val code = call.parameters["code"]
                println("code $code")
                call.respondRedirect("https://google.com")
            }
        }
    }.start(wait = true)
}

以及应用的 Dockerfile


#FROM openjdk:8
FROM gradle:6.7-jdk8

WORKDIR /var/www/html
RUN mkdir -p ./app/
WORKDIR /var/www/html/app
COPY build.gradle.kts .
COPY gradle.properties .
COPY settings.gradle.kts .
COPY Redirect/src ./Redirect/src
COPY Redirect/build.gradle.kts ./Redirect/build.gradle.kts
COPY gradlew .
COPY gradle ./gradle
EXPOSE 8080

USER root
WORKDIR /var/www/html
RUN pwd
RUN ls
RUN chown -R gradle ./app
USER gradle
WORKDIR /var/www/html/app
RUN ./gradlew run

使用这个设置我有两个问题

第一个问题:

当我 运行 docker-compose.exe up --build 我在 val ds = HikariDataSource(config) 线上收到异常 HikariPool$PoolInitializationException: Failed to initialize pool: The connection attempt failed. 我为 postgres (172.20.0.6) 设置了静态 ip,当我在 PGAdmin 中使用这个 ip 时它可以工作,所以为什么我的应用程序无法连接到 postgres?

第二题:

我尝试测试应用程序是否正常启动,并且在大多数基础知识中一切正常。所以我评论了所有与数据库连接相关的源代码,因为那时我 运行 docker-compose.exe up --build 我的应用程序只显示第 [=22= 行的字母 e ] 此时一切似乎都被冻结了,postgres 和 PGAdmin 没有启动,之后容器似乎没有响应并且应用程序在端口 5000 或 8080 上没有响应。有什么办法可以 运行 应用程序所以它不会阻止其他部分的执行?

第一个问题: 我开始使用主机名而不是 IP 地址,所以现在我使用 postgres 而不是 172.20.0.6。其余部分与第二个问题有关

第二题:

问题是我在容器的构建阶段启动应用程序。

相反RUN ./gradlew run我用

RUN gradle build
ENTRYPOINT ["gradle","run"]

我还注意到我在使用 FROM gradle:6.7-jdk8

时不必使用 gradle 包装器

现在一切正常。