Деплой Spring Boot/PostgreSQL проекта через Gradle и Docker

237
15 февраля 2018, 14:59

Здравствуйте. Возникла проблема с деплоем, над которой я уже бьюсь больше суток. Ситуация такая: пишу бэкенд для мобильных приложений на стеке:

  1. Spring Boot 1.5 + Dev Tools
  2. PostgreSQL
  3. Docker
  4. Gradle

docker-compose.yml

version: '3'
services:
    web:
      image: mobilebackend      
      ports:
          - 8088:8080
      depends_on:
          - db
      links:
         - db
    db:
        container_name: transneft_db
        image: postgres
        restart: always
        volumes:
            - transneft_db:/var/lib/postgresql/data
        environment:
            - POSTGRES_PASSWORD=pass
            - POSTGRES_USER=user
            - POSTGRES_DB=db
            - PGDATA=/var/lib/postgresql/data/pgdata
        ports:
            - 54320:5432
    adminer:
        image: adminer
        restart: always
        ports:
            - 8082:8080
volumes:
    transneft_db: {}

application.properties

spring.datasource.url=jdbc:postgresql://localhost:54320/db
spring.datasource.username=user
spring.datasource.password=pass
spring.datasource.platform=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.database=POSTGRESQL
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
jwt.secret =aotransneftsibir
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

build.gradle

buildscript {
    ext {
        springBootVersion = '1.5.10.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath('se.transmode.gradle:gradle-docker:1.2')
    }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'docker'
apply plugin: 'application'
repositories {
    mavenCentral()
}
compileJava {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    mainClassName       = "com.backend.MobilebackendApplication"
}
jar {
    baseName = "backend-api"
    group    = "com.backend"
    version  = "0.0.1-SNAPSHOT"
    manifest { attributes "Main-Class": "com.backend.mobilebackend.MobilebackendApplication" }
}
docker {
    baseImage "frolvlad/alpine-oraclejdk8:slim"
    maintainer 'Alex Scrobot "scrobot91@gmail.com"'
}
dependencies {
    // spring boot
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-data-rest')
    compile('org.springframework.boot:spring-boot-starter-web')
    runtime('org.springframework.boot:spring-boot-devtools')
    //postgresql
    runtime('org.postgresql:postgresql')
    //gson
    compile group: 'com.google.code.gson', name: 'gson', version: '2.7'
    // JWT
    compile 'io.jsonwebtoken:jjwt:0.9.0'
    //test env
    testCompile('org.springframework.boot:spring-boot-starter-test')
    testCompile('org.springframework.security:spring-security-test')
}

На локалхосте все отлично запускается, когда контейнер с постгресом запущен, все работает, все отлично.

Проблемы начинаются, когда я пытаюсь вызвать

./gradlew build distDocker --refresh-dependencies

В этом случае в spring.datasource.url должен обязательно стоять localhost, иначе билд образа сфейлится. В итоге, собранный образ из градла я пытаюсь поднять docker-compose'ом, и получаю ошибку соединения с БД. В причинах я разобрался, схема такая:

контейнер с .jar поднимается, пытается постучаться по localhost:db_port, но внутри контейнера он найти его не может, естественно. Поэтому нужно указать вместо localhost:db_port -> db:db_port, где db - это service_name из docker-compose.yml Но, тут начинается самое интересное, при сборке образа, спринг просто не может увидеть db:db_port, и билд фейлится.. Что делать - не знаю.. Мне начинает казаться, что я слишком тупой для таких высоких технологий))) Подскажите пожалуйста, может я неправильно все понял, И проблема решается за 1 минуту?

Answer 1

Рекомендую вам внутри кластера также поднять виртуальную сеть, например:

networks:
  main:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: *.*.0.0/24
          gateway: *.*.0.1

где main - это имя сети. Теперь для каждого контейнера в кластере можно указать эту сеть в качестве размещения, а также IP-адрес:

networks:
  main:
    ipv4_address: 172.30.0.12

Подробно работа с сетями на кластере Compose описана в разделе Networking in Compose официальной документации.

P.S.: Не будьте к себе так критичны))

Answer 2

На самом деле, дело было не в бобине)))) Разобравшись в вопросе мапинга сетей, мне открылась истина: соединение между контейнерами идет через внутреннюю сеть, маппинг на хост это просто настройка haproxy в составе докера, который будет перенаправлять запросы на хостовую машину в контейнер, а на сеть самого контейнера маппинг не влияет никоим образом. Таким образом, приложение должно искать БД на db:5432, а вот БД интерфейс, в моем случае adminer, уже ищет конект на localhost:54320

READ ALSO
java. Hibernate. transactionManager

java. Hibernate. transactionManager

Не могу настроить transactionManager

258
Что отправлять на выполнение в тредпулл, runnable или thread

Что отправлять на выполнение в тредпулл, runnable или thread

Создал executor с единственным потоком,

256
Где найти развернутое описание класса BigDecimal?

Где найти развернутое описание класса BigDecimal?

Добрый день, на каком русскоязычном сайте можно прочесть разжеванную для новичка информацию про использования класса BigDecimal, в частности...

178