Migrate To Docker Environment.

Overview

This will guide you to deploy your entire demo system in docker environment by creating docker images step by step.

We only focus on the configuration files and manifest files for docker deployment and how the communication is happened in the docker environment. Please find the full source code here.

stacksaga demo docker summary

The steps are as follows.

  1. [Set up StackSaga-Admin server].

  2. Updating api-gateway service.

  3. Updating eureka-service service.

  4. Updating order-service service.

  5. Updating user-service service.

  6. Updating stock-service service.

  7. Updating payment-service service.

Set up StackSaga-Admin server in Docker.

Instead of running the executable jar fil in the local, you can use the StackSaga-Admin-Server image called stacksaga/stacksaga_admin_mysql from the docker-hub.

Let’s create the docker-compose file for running the StackSaga-Admin-Server and configure the database for the StackSaga-Admin-Server.

we create 3 different network groups in this example for grouping the services based on the communication.
  1. stacksaga-admin-communicate group

    1. admin_db service. (from docker-compose.admin.yaml)

    2. stacksaga-admin service. (from docker-compose.admin.yaml)

    3. order-service service. (from docker-compose.services.yaml)

  2. api-gateway-communicate group

    1. api-gateway service. (from docker-compose.services.yaml)

    2. payment-service service. (from docker-compose.services.yaml)

    3. user-service service. (from docker-compose.services.yaml)

    4. order-service service. (from docker-compose.services.yaml)

  3. utility-server-communicate group

    1. db service. (from docker-compose.services.yaml)

    2. eureka-service service. (from docker-compose.services.yaml)

    3. api-gateway service. (from docker-compose.services.yaml)

    4. order-service service. (from docker-compose.services.yaml)

    5. user-service service. (from docker-compose.services.yaml)

    6. payment-service service. (from docker-compose.services.yaml)

docker-compose.admin.yaml
version: '3.8'
services:
  admin_db: (1)
    container_name: admin_db
    image: mysql:8.0 (2)
    restart: always
    environment: (3)
      MYSQL_ROOT_PASSWORD: mafei
      MYSQL_USER: mafei
      MYSQL_PASSWORD: mafei
    ports:
      - "3506:3306" (4)
    volumes:
      - admin_mysql_data:/var/lib/mysql (5)
    healthcheck: (6)
      test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
      timeout: 20s
      retries: 10
    networks:
      - stacksaga_admin (7)
  stacksaga-admin: (8)
    container_name: stacksaga-admin
    image: stacksaga/stacksaga_admin_mysql:1.0.0 (9)
    restart: always
    ports:
      - "4444:4444" (10)
    environment: (11)
      - SPRING_DATASOURCE_URL=jdbc:mysql://admin_db:3306/stacksaga_admin?createDatabaseIfNotExist=true
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=mafei
    depends_on:
      admin_db:
        condition: service_healthy (12)
    networks:
      - stacksaga_admin (13)
volumes:
  admin_mysql_data: (14)
    driver: local

networks:
  stacksaga_admin: (15)
    driver: bridge

Highlights

1 Create a service for the database called admin_db.
2 Mysql version 8 is used as the image. This is the minimum version that supports StackSaga framework)
3 Pass the initial username and password for creating the database server.
4 Due to you many have run the local mysql the internal port exports in port 3506 for out of the docker environment.
5 Use the volume admin_mysql_data that we created for saving the mysql-image’s data in the allocated disk.
6 The StackSaga-Admin-Server should use the database that we are creating. Therefore, we have to confirm that the stacksaga-admin server run after successfully starting the admin_db. The command tha we have mentioned in the test will be called until it returns a success response.
7 admin_db server has been added to the stacksaga_admin group. because the database and the stacksaga-admin should communicate via the host.
8 creating the stacksaga-admin service for deploying the stacksaga_admin_mysql image.
9 The stacksaga/stacksaga_admin_mysql:1.0.0 is used for running the admin-server.
10 The port of the admin-server container is exposed to the outside with port 4444. Then you can access the admin-dashboard via localhost:4444.
11 Passing the required configurations as environment variables. The database host and username and password of the database that we created above for the admin-server is added here.
12 Avoid running the admin-server before starting the mysql server successfully.
13 Add the stacksaga-admin server into the stacksaga_admin network group.
14 Creating the volume for storing the mysql database data in the allocated disk named admin_mysql_data.
15 Creating the network group that we used above named stacksaga_admin.
application-docker.yml
eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka-service:8085/eureka/
  instance:
    instance-id: ${spring.application.name}:${random.uuid}
    prefer-ip-address: true
server:
  port: 8080
management:
  info:
    env:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*"
info:
  app:
    author: mafei
    name: ${spring.application.name}
    version: 1.0.0
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/*/stacksaga/**]':
            allowedOrigins:
              - "http://localhost:4444"
            allowedMethods: "*"
            allowedHeaders: "*"
      default-filters:
        - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
      discovery:
        locator:
          lower-case-service-id: true
          enabled: true
application-docker.yaml
eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
server:
  port: 8085

management:
  info:
    env:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*"
info:
  app:
    author: mafei
    name: ${spring.application.name}
    version: 1.0.0
application-docker.yaml
services:
  payment-service: http://payment-service
  stock-service: http://stock-service
  user-service: http://user-service
server:
  port: 8080
eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka-service:8085/eureka/
  instance:
    instance-id: ${spring.application.name}:${random.uuid}
    prefer-ip-address: true
spring:
  application:
    name: order-service
  datasource:
    username: root
    password: mafei
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://db:3306/stacksaga_place_order_demo_order_service?createDatabaseIfNotExist=true
  liquibase:
    enabled: false
stacksaga:
  component-scan: org.example.aggregator
  app-release-version: 1.0.0
  connect:
    admin-urls:
      - http://stacksaga-admin:4444
    admin-username: order-service-application-user
    admin-password: ykLO89Irx2Q6Cf2j
  datasource:
    mysql:
      jdbc-url: jdbc:mysql://db:3306/order-service?createDatabaseIfNotExist=true
      username: root
      password: mafei
      driver-class-name: com.mysql.cj.jdbc.Driver
  enable: true
  cloud:
    validate-internal-communication-on-start-up: false

management:
  endpoint:
    env:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*"
info:
  app:
    author: mafei
    name: ${spring.application.name}
    version: ${stacksaga.app-release-version}
logging:
  level:
    org:
      stacksaga: debug
application-docker.yaml
server:
  port: 8080
spring:
  application:
    name: payment-service
  datasource:
    username: root
    password: mafei
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://db:3306/stacksaga_place_order_demo_payment_service?createDatabaseIfNotExist=true
  jpa:
    hibernate:
      ddl-auto: update
eureka:
  client:
    service-url:
      defaultZone: http://eureka-service:8085/eureka/
  instance:
    instance-id: ${spring.application.name}:${random.uuid}
    prefer-ip-address: true
management:
  endpoint:
    env:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*"
info:
  app:
    author: mafei
    name: ${spring.application.name}
    version: 1.0.0
logging:
  level:
    org:
      stacksaga: debug
      springframework: debug
    root: info
server:
  port: 8080
spring:
  application:
    name: stock-service
  datasource:
    username: root
    password: mafei
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://db:3306/stacksaga_place_order_demo_stock_service?createDatabaseIfNotExist=true
  jpa:
    hibernate:
      ddl-auto: update
eureka:
  client:
    service-url:
      defaultZone: http://eureka-service:8085/eureka/
  instance:
    instance-id: ${spring.application.name}:${random.uuid}
    prefer-ip-address: true
management:
  endpoint:
    env:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*"
info:
  app:
    author: mafei
    name: ${spring.application.name}
    version: 1.0.0
logging:
  level:
    org:
      stacksaga: debug
      springframework: debug
    root: info
server:
  port: 8080
spring:
  application:
    name: user-service
  datasource:
    username: root
    password: mafei
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://db:3306/stacksaga_place_order_demo_user_service?createDatabaseIfNotExist=true
  jpa:
    hibernate:
      ddl-auto: update
eureka:
  client:
    service-url:
      defaultZone: http://eureka-service:8085/eureka/
  instance:
    instance-id: ${spring.application.name}:${random.uuid}
    prefer-ip-address: true
management:
  endpoint:
    env:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*"
info:
  app:
    author: mafei
    name: ${spring.application.name}
    version: 1.0.0
logging:
  level:
    org:
      stacksaga: debug
      springframework: debug
    root: info