Snippet Path

Auto-testing a service with database and migration in a gitlab pipeline using compose

Authors

Docker Compose

$root/test/docker-compose.yml
services:
  postgres:
    build:
      context: test
      dockerfile: postgres.test.Dockerfile
    tmpfs: /var/lib/postgresql/data
    networks:
      - myapp_test_network
    environment:
      - POSTGRES_HOST_AUTH_METHOD=trust
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  migrator:
    build:
      context: .
      dockerfile: Dockerfile.migrate.test
    entrypoint: sh
    command: -c "sleep 2 && JOB_DONE='no' && migrate -path=/migrations/v1 -database postgres://DBUSERNAME:DBPASSWORD@postgres:5432/DBNAME?sslmode=disable up && JOB_DONE='yes' && sleep infinity"
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "if [ $$JOB_DONE=='yes' ]; then exit 0 ; else exit 1; fi"]
      interval: 5s
      timeout: 10s
      retries: 10
    links:
      - postgres
    networks:
      - myapp_test_network

  mainserviceautotest:
    build:
      context: .
      dockerfile: Dockerfile.test
    command: go test ./... -run . -count 1 -args -dotenv-dir .
    depends_on:
      postgres:
        condition: service_healthy
      migrator:
        condition: service_healthy
    links:
      - postgres
    tmpfs: /app_directory
    networks:
      - myapp_test_network
    environment:
      - SRV_DB_HOST=postgres
      - SRV_DB_PORT=5432
      - SRV_DB_DATABASE=DBNAME
      - SRV_DB_USER=DBUSERNAME
      - SRV_DB_PASSWORD=DBPASSWORD

networks:  
  myapp_test_network:
    driver: bridge

Postgres with custom locale

$root/test/postgres.test.Dockerfile
FROM postgres:14.1
# RUN initdb --locale=fa_IR
RUN locale-gen fa_IR.UTF-8 
RUN localedef -i fa_IR -c -f UTF-8 -A /usr/share/locale/locale.alias fa_IR.UTF-8
ENV LANG fa_IR.utf8
COPY ./scripts/db/create_db.sql /docker-entrypoint-initdb.d/

DB init script

$root/test/scripts/db/create_db.sql
CREATE DATABASE DNAME
	WITH
	OWNER = postgres
	TEMPLATE = template0
	ENCODING = 'UTF8'
	LC_COLLATE = 'fa_IR.UTF8'
	LC_CTYPE = 'fa_IR.UTF8'
    TABLESPACE = pg_default
	CONNECTION LIMIT = -1;

Migrator Dockerfile

$root/Dockerfile.migrate.test
FROM migrate/migrate as migrator

COPY scripts/db/v1 /migrations/v1

CMD [""]
ENTRYPOINT [ "sh" ]

Test Run Container Dockerfile

$root/Dockerfile.test
FROM golang:1.18-buster AS builder

WORKDIR /go/src/domain.com/MYAPP/

COPY go.mod go.sum ./
RUN go mod download

COPY . .

CMD [""]

Gitlab CI

$root/.gitlab-ci.yml
build:
    stage: build
    script:
        - "..."
        - |
            docker compose -f test/docker-compose.yml --project-directory "$CI_PROJECT_DIR" up --build --force-recreate -V --abort-on-container-exit --exit-code-from mainserviceautotest
            docker compose -f test/docker-compose.yml down -v
        - "..."