理系学生日記

おまえはいつまで学生気分なのか

Docker ComposeでPostgresバックエンドのgitbucket/redmineを構築する

Redmine をマジメに使ったことがなかったのですが、使う機会が多くなってきているので、ちょっと慣れとかないと厳しいなぁと思っておりました。 とりあえず本を買ったは良いのですが、手元で確認したいというのと、同じく良く使われるようになってきている Gitbucket も手元で使いたい、 それに、せっかくだったら全部 Postgresql をバックエンドにしておきたいという思いもありました。

というわけで、これらの環境を手元にサクっと構築できるように、Docker Compose で立ち上げられるようにしておくか、というのが本エントリの趣旨になります。

これにより、以下のコマンドで、redmine と gitbucket が動き出します。

$ docker-compose run -d

ベースとなるコンテナ

ベースとしたのは以下のコンテナです。

コンテナ URL
redmine:3.3.3 redmine
postgres:9.6.2 postgres
takezoe/gitbucket:4 gitbucket

Redmine

Redmine のコンテナについては、環境変数でバックエンドの DB を切り替えられるようになっています。このため、docker-compose.yml に何の工夫もなく記述するだけで良くて楽でした。

docker-compose.yml 上のサービス定義は以下のようになります。

  redmine:
    image: redmine:3.3.3
    ports:
      - 3000:3000
    environment:
      REDMINE_DB_POSTGRES: db
      REDMINE_DB_USERNAME: postgres
      REDMINE_DB_PASSWORD: password
    depends_on:
      - db
    restart: always

Gitbucket

Gitbucket については、以下の 2 つの課題がありました。

  1. Gitbucket はデータベース設定は設定ファイル database.conf で持つようになっているため、バックエンドを Postgres に設定した database.conf を使ってコンテナをビルドしておく必要があります。つまり、Dockerfile を作っておく必要がある。
  2. Gitbucket は起動時にデータベーススキーマを作るので、Postgres のコンテナ上で Postgres が立ち上がるまで Gitbucket の起動を待つ必要がある

前者は Dockerfile で ADD を使えば問題ないです。

後者については、コンテナの依存関係を示す depends_on だけではダメで、Postgresql の LISTEN ポートが有効になるまで待つ仕組みを入れる必要があります。 これを簡単に実現するのが wait-for-it.sh という Bash スクリプトです。 このスクリプトは、一定時間ほど指定された host:port の open を試み、その状態でブロックしてくれるというものです。

実装を見ると、/dev/tcp へのリダイレクトでこれを実現しておりまして、これで TCP open してくれるんや…知らんかった…。

というわけで、この wait-for-it.sh を組み込んだ Dockerfile はこちら。

# -*- mode: Dockerfile -*-
FROM takezoe/gitbucket

MAINTAINER kiririmode

ADD database.conf /gitbucket/database.conf
ADD wait-for-it/wait-for-it.sh /gitbucket/wait-for-it.sh

この Dockerfile をベースにして、docker-compose.yml のサービス定義は以下のようになります。

  gitbucket:
    build:
      context: .
      dockerfile: Dockerfile.gitbucket
    ports:
      - 8080:8080
    command: ["/gitbucket/wait-for-it.sh", "db:5432", "--", "java", "-jar", "/opt/gitbucket.war"]
    depends_on:
      - db
    restart: always

Postgresql

Postgres も特に特筆すべきことはしていないのですが、Gitbucket の前提が「起動時にデータベースがあること」なので、そのデータベースを作るように設定します。

Postgres のコンテナは、/docker-entrypoint-initdb.d というディレクトリに放り込んだスクリプトを起動時に実行してくれるので、以下のようなスクリプトを init-gitbucket-db.sh として保存しておいて、Dockerfile の ADD を使って送り込めば良い。

#!/bin/bash

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<EOF
    CREATE USER gitbucket PASSWORD 'password';
    CREATE DATABASE gitbucket;
    GRANT ALL PRIVILEGES ON DATABASE gitbucket TO gitbucket;
EOF

docker-compose.yml のサービス定義は以下のとおりです。

  db:
    build:
      context: .
      dockerfile: Dockerfile.postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    restart: always

つくったもの