docker-composeで構築したGitLabとRedmineのリポジトリ共有

GitLabとRedmineの投稿が多いのに
この2つの連携について書いてないなと思ったので書きます。

具体的に何を構築するかというと こちら
RedmineでGitLabのリポジトリを見れるようにします。

今回の実行環境は以下の通り。

$ cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
$ docker --version
Docker version 19.03.12, build 48a66213fe
$ docker-compose --version
docker-compose version 1.26.1, build f216ddbf 

また、以下のようなディレクトリ構成とします。
docker-compose.ymlを分割して外部ネットワークでつなげます。

.
├── gitlab
│   └── docker-compose.yml
├── proxy
│   ├── docker-compose.yml
│   └── ssl.conf
└── redmine
    └── docker-compose.yml

まず共通で接続するネットワークを作成します。
今回はtsuchinokoというネットワークにしました。

$ docker network create tsuchinoko

さらに、別のdocker-compose.ymlで構築されたRedmineで
GitLabのボリュームにアクセスするために外部共有用のボリュームを作成します。
(今回試したかったのはこれ)

$ docker volume create --name=gitlab-data

では、gitlab/docker-compose.ymlでGitLabを起動します。
いつものようにsameersbn/gitlab を使わせていただきます。
元々のdocker-compose.ymlから少し変えている部分があります。
一番下のvolumesとnetworksがポイントですかね。

version: '3.4'

services:
  gitlab_redis:
    restart: always
    image: redis:5.0.9
    container_name: gitlab_redis
    command:
    - --loglevel warning
    volumes:
    - redis-data:/var/lib/redis:Z

  gitlab_postgresql:
    restart: always
    image: sameersbn/postgresql:11-20200524
    container_name: gitlab_postgresql
    volumes:
    - postgresql-data:/var/lib/postgresql:Z
    environment:
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production
    - DB_EXTENSION=pg_trgm

  gitlab:
    restart: always
    image: sameersbn/gitlab:13.0.6
    container_name: gitlab
    depends_on:
    - gitlab_redis
    - gitlab_postgresql
    ports:
    - "10080:80"
    - "10022:22"
    volumes:
    - gitlab-data:/home/git/data:Z
    healthcheck:
      test: ["CMD", "/usr/local/sbin/healthcheck"]
      interval: 5m
      timeout: 10s
      retries: 3
      start_period: 5m
    environment:
    - DEBUG=false

    - DB_ADAPTER=postgresql
    - DB_HOST=gitlab_postgresql
    - DB_PORT=5432
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production

    - REDIS_HOST=gitlab_redis
    - REDIS_PORT=6379

    - TZ=Asia/Tokyo
    - GITLAB_TIMEZONE=Tokyo

    - GITLAB_HTTPS=false
    - SSL_SELF_SIGNED=false

    - GITLAB_HOST=example.tsuchinokometal.com
    - GITLAB_PORT=10080
    - GITLAB_SSH_PORT=10022
    - GITLAB_RELATIVE_URL_ROOT=/gitlab
    - GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alphanumeric-string
    - GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alphanumeric-string
    - GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alphanumeric-string

    - GITLAB_ROOT_PASSWORD=
    - GITLAB_ROOT_EMAIL=

    - GITLAB_NOTIFY_ON_BROKEN_BUILDS=true
    - GITLAB_NOTIFY_PUSHER=false

    - GITLAB_EMAIL=notifications@example.com
    - GITLAB_EMAIL_REPLY_TO=noreply@example.com
    - GITLAB_INCOMING_EMAIL_ADDRESS=reply@example.com

    - GITLAB_BACKUP_SCHEDULE=daily
    - GITLAB_BACKUP_TIME=01:00

    - SMTP_ENABLED=false
    - SMTP_DOMAIN=www.example.com
    - SMTP_HOST=smtp.gmail.com
    - SMTP_PORT=587
    - SMTP_USER=mailer@example.com
    - SMTP_PASS=password
    - SMTP_STARTTLS=true
    - SMTP_AUTHENTICATION=login

    - IMAP_ENABLED=false
    - IMAP_HOST=imap.gmail.com
    - IMAP_PORT=993
    - IMAP_USER=mailer@example.com
    - IMAP_PASS=password
    - IMAP_SSL=true
    - IMAP_STARTTLS=false

    - OAUTH_ENABLED=false
    - OAUTH_AUTO_SIGN_IN_WITH_PROVIDER=
    - OAUTH_ALLOW_SSO=
    - OAUTH_BLOCK_AUTO_CREATED_USERS=true
    - OAUTH_AUTO_LINK_LDAP_USER=false
    - OAUTH_AUTO_LINK_SAML_USER=false
    - OAUTH_EXTERNAL_PROVIDERS=

    - OAUTH_CAS3_LABEL=cas3
    - OAUTH_CAS3_SERVER=
    - OAUTH_CAS3_DISABLE_SSL_VERIFICATION=false
    - OAUTH_CAS3_LOGIN_URL=/cas/login
    - OAUTH_CAS3_VALIDATE_URL=/cas/p3/serviceValidate
    - OAUTH_CAS3_LOGOUT_URL=/cas/logout

    - OAUTH_GOOGLE_API_KEY=
    - OAUTH_GOOGLE_APP_SECRET=
    - OAUTH_GOOGLE_RESTRICT_DOMAIN=

    - OAUTH_FACEBOOK_API_KEY=
    - OAUTH_FACEBOOK_APP_SECRET=

    - OAUTH_TWITTER_API_KEY=
    - OAUTH_TWITTER_APP_SECRET=

    - OAUTH_GITHUB_API_KEY=
    - OAUTH_GITHUB_APP_SECRET=
    - OAUTH_GITHUB_URL=
    - OAUTH_GITHUB_VERIFY_SSL=

    - OAUTH_GITLAB_API_KEY=
    - OAUTH_GITLAB_APP_SECRET=

    - OAUTH_BITBUCKET_API_KEY=
    - OAUTH_BITBUCKET_APP_SECRET=

    - OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL=
    - OAUTH_SAML_IDP_CERT_FINGERPRINT=
    - OAUTH_SAML_IDP_SSO_TARGET_URL=
    - OAUTH_SAML_ISSUER=
    - OAUTH_SAML_LABEL="Our SAML Provider"
    - OAUTH_SAML_NAME_IDENTIFIER_FORMAT=urn:oasis:names:tc:SAML:2.0:nameid-format:transient
    - OAUTH_SAML_GROUPS_ATTRIBUTE=
    - OAUTH_SAML_EXTERNAL_GROUPS=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_USERNAME=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME=

    - OAUTH_CROWD_SERVER_URL=
    - OAUTH_CROWD_APP_NAME=
    - OAUTH_CROWD_APP_PASSWORD=

    - OAUTH_AUTH0_CLIENT_ID=
    - OAUTH_AUTH0_CLIENT_SECRET=
    - OAUTH_AUTH0_DOMAIN=
    - OAUTH_AUTH0_SCOPE=

    - OAUTH_AZURE_API_KEY=
    - OAUTH_AZURE_API_SECRET=
    - OAUTH_AZURE_TENANT_ID=

volumes:
  redis-data:
  postgresql-data:
  gitlab-data:
    external: true

networks:
  default:
    external:
      name: tsuchinoko

次にredmine/docker-compose.ymlでRedmineを起動します。
sameersbn/redmine を使わせていただきます。
なんとなくmemcachedを追加してます。(ちゃんと使えているかは不明)
ポイントは、やはりvolumesとnetworks。
あとRedmineのコンテナでgitlab-dataをマウントしてます。

version: '3'

services:
  redmine_postgresql:
    image: sameersbn/postgresql:9.6-4
    container_name: redmine_postgresql
    environment:
    - DB_USER=redmine
    - DB_PASS=password
    - DB_NAME=redmine_production
    volumes:
    - redmine-postgresql:/var/lib/postgresql

  redmine_memcached:
    image: sameersbn/memcached:1.5.6-2
    container_name: redmine_memcached
    ports:
    - "11211:11211"
    restart: always

  redmine:
    image: sameersbn/redmine:4.1.1-3
    container_name: redmine
    depends_on:
    - redmine_postgresql
    environment:
    - TZ=Asia/Tokyo

    - DB_ADAPTER=postgresql
    - DB_HOST=redmine_postgresql
    - DB_PORT=5432
    - DB_USER=redmine
    - DB_PASS=password
    - DB_NAME=redmine_production

    - MEMCACHE_HOST=redmine_memcached
    - MEMCACHE_PORT=11211

    - REDMINE_PORT=10083
    - REDMINE_HTTPS=false
    - REDMINE_RELATIVE_URL_ROOT=/redmine
    - REDMINE_SECRET_TOKEN=

    - REDMINE_SUDO_MODE_ENABLED=false
    - REDMINE_SUDO_MODE_TIMEOUT=15

    - REDMINE_CONCURRENT_UPLOADS=2

    - REDMINE_BACKUP_SCHEDULE=
    - REDMINE_BACKUP_EXPIRY=
    - REDMINE_BACKUP_TIME=

    - SMTP_ENABLED=false
    - SMTP_METHOD=smtp
    - SMTP_DOMAIN=www.example.com
    - SMTP_HOST=smtp.gmail.com
    - SMTP_PORT=587
    - SMTP_USER=mailer@example.com
    - SMTP_PASS=password
    - SMTP_STARTTLS=true
    - SMTP_AUTHENTICATION=:login

    - IMAP_ENABLED=false
    - IMAP_HOST=imap.gmail.com
    - IMAP_PORT=993
    - IMAP_USER=mailer@example.com
    - IMAP_PASS=password
    - IMAP_SSL=true
    - IMAP_INTERVAL=30

    ports:
    - "10083:80"
    volumes:
    - redmine-data:/home/redmine/data
    - gitlab-data:/home/git/data

volumes:
  redmine-postgresql:
  redmine-data:
  gitlab-data:
    external: true

networks:
  default:
    external:
      name: tsuchinoko

こちらはおまけです。 サブディレクトリでGitLabとRedmineにアクセスするために
nginxをリバースプロキシとして使います。
自己証明書でhttpsにしていますが、この辺りの手順は以前書いた こちら を参考に構築してください。


2021/5/30 更新
Let’s Encryptの正規証明書を使ったhttps化は こちら をご確認ください。


ssl.confは以下としました。

server {
    root /dev/null;
    server_name example.tsuchinokometal.com;
    charset UTF-8;
    access_log /var/log/nginx/example.tsuchinokometal.com.access.log;
    error_log /var/log/nginx/example.tsuchinokometal.com.error.log;

    # Set up SSL only connections:
    listen *:443 ssl http2;
    ssl_certificate             /certs/example.tsuchinokometal.com.crt;
    ssl_certificate_key         /certs/example.tsuchinokometal.com.key;

    ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4';
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_session_timeout  5m;

    client_max_body_size        0;
    chunked_transfer_encoding   on;

    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
    
    location /gitlab {
        proxy_pass http://gitlab;
    }
    location /redmine {
        proxy_pass http://redmine;
    }
    
}

server {
    listen *:80;
    server_name  example.tsuchinokometal.com;
    server_tokens off; ## Don't show the nginx version number, a security best practice
    return 301 https://$http_host:$request_uri;
}

proxy/docker-compose.ymlはこちら。
地味にcertsも外部共有しています。
作成した証明書などをボリューム内にコピーしてくださいね。

version: '3'

services:
  nginx:
    image: nginx:stable
    container_name: nginx_proxy
    volumes:
      - ./ssl.conf:/etc/nginx/conf.d/ssl.conf
      - certs:/certs
    ports:
      - "80:80"
      - "443:443"

volumes:
  certs:
    external: true

networks:
  default:
    external:
      name: tsuchinoko

無事構築が完了したらGitLabで適当なプロジェクトを作成します。
今回はtestグループのhogeプロジェクトです。
README.mdだけコミットしておきます。

gitlab_redmine_integrate_001.png

そうするとRedmineのコンテナ内で
/home/git/data/repositories/test/hoge.gitが…

$ docker exec -it redmine ls -la /home/git/data/repositories/
total 4
drwxr-sr-x.  3 redmine redmine  17 Jul  8 00:30 +gitaly
drwxrws---.  4 redmine redmine  60 Jul  9 14:16 .
drwxr-xr-x. 11 redmine redmine 133 Jul  4 23:38 ..
-rw-------.  1 redmine redmine  64 Jul  4 22:40 .gitaly-metadata
drwxr-s---.  4 redmine redmine  26 Jul  6 23:19 @hashed

ない!

何かミスったかと調べてみると13.0からハッシュストレージになったそうです。
ドキュメントはこちら

ドキュメントによると
Admin Area > Overview > Projects
のGitaly relative pathがリポジトリのパスらしいです。
見てみると、以下のようになってました。

gitlab_redmine_integrate_002.png

試しにこれでやってみます。
Redmineのプロジェクトで「設定」⇒「リポジトリ」⇒「新しいリポジトリ」

gitlab_redmine_integrate_003.png

さっきのパスで設定してみます。

gitlab_redmine_integrate_004.png

そんでもってリポジトリタブを開いてみると、

gitlab_redmine_integrate_005.png

無事表示できました。

gitlab_redmine_integrate_006.png

どうやら13.0以降でも使えるようですね。

追加で Redmine Code Review Plugin を利用するとさらに便利かもしれません。
最新版はRedmine 4.2.x にも対応しているようです。