[docker-composie] DB continer(서비스)에migration

필요조건

  • docker-compose를 통해 DB container를 시작할 때migration
  • 을 동시에 실행하고자 함
  • 이미 시작한 DB 컨테이너를migration
  • 원하는 경우
  • 가능하면 local에migration bin을 설치하지 말고 docker
  • 를 사용하십시오

    운영 환경

  • MacOS Big Sur v11.6
  • Apple M1
  • Tools


    Database
    Migration tool
    MySQL
    golang migrate
    https://github.com/golang-migrate/migrate

    결론


    file system


    다음 디렉토리 구성을 전제로 합니다.
    본 원고는 migration를 주제seed로 하고 본질이 아니기 때문에 생략합니다.
    또한 migration의 내용(DDL) 자체도 가능하며 sql 파일의 내용도 생략할 수 있습니다.
    .
    ├── db
    │   ├── conf.d
    │   │   └── my.cnf
    │   ├── migrations
    │   │   │── Dockerfile
    │   │   │── entrypoint.sh
    │   │   └── migrations
    │   │       └── 0001_init.up.sql
    │   │       └── 0001_init.down.sql
    │   │       └── 0002_xxxx.up.sql
    │   │       └── 0002_xxxx.down.sql
    │   └── seeds
    │       │── xxxx.sql
    │       │── ...
    └── docker-compose.yml
    

    docker-compose


    docker-compose.yml
    version: "3"
    
    services:
      db:
        image: mysql:5.6
        platform: linux/amd64
        environment:
          MYSQL_DATABASE: test
          MYSQL_USER: test
          MYSQL_PASSWORD: password
        ports:
          - "3306:3306"
        volumes:
          - db_volume:/var/lib/mysql:cached
          - ./db/conf.d:/etc/mysql/conf.d
      migrate:
        build: ./db/migrations
        depends_on:
          - db
        command: ["up"]
        environment:
          WAIT_HOSTS: db:3306
          MIGRATIONS_DIR: /migrations
          MYSQL_HOST: db
          MYSQL_PORT: 3306
          MYSQL_DATABASE: test
          MYSQL_USER: test
          MYSQL_PASSWORD: password
        volumes:
          - ./db/migrations/migrations:/migrations
    volumes:
      db_volume:
        driver: local
    

    migrate Dockerfile


    migrate/Dockerfile
    FROM migrate/migrate
    
    ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.9.0/wait /wait
    RUN chmod +x /wait
    
    COPY entrypoint.sh /usr/local/bin
    RUN chmod +x /usr/local/bin/entrypoint.sh
    
    ENTRYPOINT [ "entrypoint.sh" ]
    

    migrate entrypoint.sh


    migrate/entrypoint.sh
    #!/bin/sh
    
    /wait
    /migrate \
      -path $MIGRATIONS_DIR \
      -database "mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(${MYSQL_HOST}:${MYSQL_PORT})/${MYSQL_DATABASE}" \
      $@
    

    Point 1:db 대기 서비스

    docker-compose up에서 모든 서비스를 시작할 때migrationcontainer는 db(mysqld) 시작이 끝난 후에 tcp 연결을 할 수 있을 때까지 기다려야 합니다.
    docker-compose 서비스 간의 의존성은 dependes_on에서 선언적으로 정의할 수 있지만, 의존자인container가 Ready가 되기 전에 의존원container의 시작을 기다리는 것이 아니라 container의 시작 순서를 제어하는 것입니다.
    따라서 docker-compose-wait를 이용하여 특정한 서비스가ready상태로 변하기 전에 대기한다.
    migrate/Dockerfile
    ~
    
    ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.9.0/wait /wait
    RUN chmod +x /wait
    
    ~
    

    Point2: Docker entrypoint


    Googling migrateofficial docker image에서 정의ENTRYPOINT했기 때문에 위docker-compose-wait를 이용하기 위해서는 위에 ENTRYPOINT라고 써야 한다.
    https://github.com/golang-migrate/migrate/blob/master/Dockerfile
    ENTRYPOINT /wait && migrate
    
    그러나 상술한 바와 같이 주행 과정은 /bin/sh가 되어 CMDmigrate의 매개 변수로 교부할 수 없다.
    docker inspect 89ab8ebc951e (container id/name)
    
    [
        {
            "Id": "89ab8ebc951e3ee27a655960762227895d528173dcd7ba3dafc65c391ce5abee",
            "Created": "2021-12-29T09:57:56.691705503Z",
            "Path": "/bin/sh",
            "Args": [
                "-c",
                "/wait \u0026\u0026 migrate",
                "up"
            ],
    ...
    
    따라서 ENTRYPOINT는 셸 스크립트 파일로, CMD는 그 매개 변수로 실행된다.
    COPY entrypoint.sh /usr/local/bin
    RUN chmod +x /usr/local/bin/entrypoint.sh
    
    ENTRYPOINT [ "entrypoint.sh" ]
    
    migrate/entrypoint.sh
    #!/bin/sh
    
    /wait
    /migrate \
      -path $MIGRATIONS_DIR \
      -database "mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(${MYSQL_HOST}:${MYSQL_PORT})/${MYSQL_DATABASE}" \
      $@
    
    결과↓
    docker inspect 127b9306a3da
    
    [
        {
            "Id": "58b4b845757725c2623dc8df99d04f41c8e3aff9626f0ee26f1ac74bc7be77f8",
            "Created": "2021-12-29T10:16:34.032928673Z",
            "Path": "entrypoint.sh",
            "Args": [
                "up"
            ],
    ...
    
    이렇게 하면 docker-compose run의 매개 변수로migration을 할 수 있다.

    How to use


    DB 서비스 시작 시 migration 까지 실행


    docker-compose up
    

    부팅 중인 DB 서비스 추가migration


    e.g.
    docker-compose run migrate down 1
    

    migration 없이 DB만 시작하려면


    docker-compose up db
    

    좋은 웹페이지 즐겨찾기