docker-composeで開発環境全部盛りしてみた

# docker-composeで開発環境全部盛りしてみた

開発グループに必要なツールを用意しました。Gitlab、Redmineから始めて少しづつ、利用範囲を広めていった結果、だいぶマシマシになったのでレシピ公開します。

以下の環境下で動作確認済です。
Docker version 19.03.8, build afacb8b
docker-compose version 1.25.4, build 8d51620a

## こんなツールが構築できる

### 開発時に使用するツール
- Plantuml  
 [plantuml/plantuml-server](https://hub.docker.com/r/plantuml/plantuml-server)  
 redmineやgitlab内のドキュメントにPlantUMLで記述した図を埋め込むために使用します。
- Gitlab  
 [sameersbn/gitlab](https://hub.docker.com/r/sameersbn/gitlab)  
 公式ではないですがとても人気のあるdocker imageです。
- Redmine  
 [sameersbn/redmine](https://hub.docker.com/r/sameersbn/redmine)  
 公式ではないですがとても人気のあるdocker imageです。
- Jenkins  
 [jenkinsci/blueocean](https://hub.docker.com/r/jenkinsci/blueocean)  
 パイプラインを主としたblueoceanプラグインを使用することでJenkinsおじさんもイケてる見た目になります。  
- Nexus3  
 [sonatype/nexus3](https://hub.docker.com/r/sonatype/nexus3)  
 mavenやnpmのローカルキャッシュリポジトリにしたり、成果物の配布用の置き場として使用します。

### 運用時のモニタリング
- logstash  
 [docker.elastic.co/logstash/logstash](https://www.elastic.co/guide/en/logstash/current/docker.html)  
 ログ収集の中間に使用します。
- ElasticSearch  
 [docker.elastic.co/elasticsearch/elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html)  
 ログやメトリックスを貯めておきます。
- Grafana  
 [grafana/grafana](https://hub.docker.com/r/grafana/grafana/)  
 ElasticSearchのデータの可視化

### コミュニケーションツール
- RocketChat  
[rocketchat/rocket.chat](https://hub.docker.com/r/rocketchat/rocket.chat)  
slackクローン（ほぼslackと同じAPI が使用できるのでgitlab,redmine,jenkinsとの連携もできます）
- Hubot  
[rocketchat/hubot-rocketchat](https://hub.docker.com/r/rocketchat/hubot-rocketchat)  
Rocketchatのボット

## docker-composeのレシピ全文

### ファイル名 .env
docker-compose.yml と同じフォルダに入れておきます。各自の環境に合わせて設定をしてください。

社内サーバーに置いていますのでLDAP やDNS,PROXYなどの設定を入れています。

```shell:.env
# Common settings
DNS1=xxx.xxx.xxx.xxx
DNS2=xxx.xxx.xxx.xxx

SMTP_DOMAIN=xxx.xxx.xxx.xxx
SMTP_HOST=mail.xxx.xxx.xxx
SMTP_PORT=25
SMTP_USER=
SMTP_PASS=

LDAP_LABEL=xxxxxx
LDAP_HOST=xxx.xxx.xxx.xxx
LDAP_VERIFY_SSL=false
LDAP_BIND_DN=CN=xxx,CN=xxx,DC=xxx,DC=xxx,DC=xxx,DC=xxx
LDAP_PASS=xxx
LDAP_ALLOW_USERNAME_OR_EMAIL_LOGIN=true
LDAP_BASE=DC=xxx,DC=xxx,DC=xxx,DC=xxx

HTTP_PROXY=http://proxy.xxx.xxx.xxx.xxx:8080
HTTPS_PROXY=http://proxy.xxx.xxx.xxx.xxx:8080
NO_PROXY=127.0.0.1,localhost
HTTP_PROXY_HOST=http://proxy.xxx.xxx.xxx.xxx
HTTP_PROXY_PORT=8080


# PlantUML settings
PLANTUML_PORT=xxxxx

# Nexus settings
NEXUS_PORT=xxxxx

# PostgreSQL settings
POSTGRESQL_VERSION=10-2

# GitLab settings
GITLAB_VERSION=12.7.6
GITLAB_DB_USER=gitlab
GITLAB_DB_PASS=password

GITLAB_HOST=xxx.xxx.xxx.xxx
GITLAB_PORT=xxxxx
GITLAB_SSH_PORT=xxxxx
GITLAB_RELATIVE_URL_ROOT=

GITLAB_EMAIL=gitlab@xxx.xxx.xxx.xxx
GITLAB_EMAIL_REPLY_TO=noreply@example.com
GITLAB_INCOMING_EMAIL_ADDRESS=gitlab@xxx.xxx.xxx.xxx
GITLAB_ROOT_PASSWORD=password

GITLAB_PROJECTS_ISSUES=true
GITLAB_PROJECTS_MERGE_REQUESTS=true
GITLAB_PROJECTS_WIKI=true
GITLAB_PROJECTS_SNIPPETS=true
GITLAB_PROJECTS_BUILDS=true
GITLAB_PROJECTS_CONTAINER_REGISTRY=true
GITLAB_PAGES_ENABLED=true
GITLAB_MATTERMOST_ENABLED=true

# Redmine settings
REDMINE_VERSION=4.1.0
REDMINE_DB_USER=redmine
REDMINE_DB_PASS=password

REDMINE_PORT=xxxxx

# Jenlins settings
JENKINS_PORT=xxxxx

# ElasticSearch settings
ES_VERSION=7.6.1
ES_PORT=9200
LOGSTASH_PORT=9600
GRAFANA_VERSION=latest
GRAFANA_PORT=xxxxx
ELASTICSEARCH_PROTO=http
ELASTICSEARCH_HOST=elasticsearch
ELASTICSEARCH_PORT=9200

# Rocketchat settings
ROCKETCHAT_VERSION=3.0.3
ROCKETCHAT_URL=http://xxx.xxx.xxx.xxx:yyyyy
ROCKETCHAT_PORT=yyyyy

HUBOT_PORT=xxxxx
```

### ファイル名 docker-compose.yml

```yaml:docker-compose.yml
version: '2'

services:
# Settings for PlantUML
  plantuml:
    image: plantuml/plantuml-server:jetty
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}
    ports:
      - "${PLANTUML_PORT}:8080"

  gitlab-redis:
    image: sameersbn/redis:latest
    command:
      - --loglevel warning
    volumes:
      - gitlab-redis-vol:/var/lib/redis:Z

  gitlab-db:
    image: sameersbn/postgresql:${POSTGRESQL_VERSION}
    volumes:
      - gitlab-db-vol:/var/lib/postgresql:Z
    environment:
      - DB_USER=${GITLAB_DB_USER}
      - DB_PASS=${GITLAB_DB_PASS}
      - DB_NAME=gitlabhq_production
      - DB_EXTENSION=pg_trgm

# Settings For Gitlab
  gitlab:
    image: sameersbn/gitlab:${GITLAB_VERSION}
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    depends_on:
      - gitlab-redis
      - gitlab-db
    ports:
      - "${GITLAB_PORT}:80"
      - "${GITLAB_SSH_PORT}:22"
    volumes:
      - gitlab-vol:/home/git/data:Z
      - gitlab-socket-vol:/var/run/docker.sock
    environment:
      - DEBUG=false
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}

      - DB_ADAPTER=postgresql
      - DB_HOST=gitlab-db
      - DB_PORT=5432
      - DB_USER=${GITLAB_DB_USER}
      - DB_PASS=${GITLAB_DB_PASS}
      - 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=${GITLAB_HOST}
      - GITLAB_PORT=${GITLAB_PORT}
      - GITLAB_SSH_PORT=${GITLAB_SSH_PORT}
      - GITLAB_RELATIVE_URL_ROOT=${GITLAB_RELATIVE_URL_ROOT}

      - 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=gitlab@example.com
      - GITLAB_EMAIL_REPLY_TO=noreply@example.com
      - GITLAB_INCOMING_EMAIL_ADDRESS=reply@example.com
      - GITLAB_SIGNUP_ENABLED=false
      - GITLAB_BACKUP_SCHEDULE=daily
      - GITLAB_BACKUP_EXPIRY=604800
      - GITLAB_BACKUP_TIME=01:00

      - SMTP_ENABLED=true
      - SMTP_DOMAIN=${SMTP_DOMAIN}
      - SMTP_HOST=${SMTP_HOST}
      - SMTP_PORT=${SMTP_PORT}
      - SMTP_USER=${SMTP_USER}
      - SMTP_PASS=${SMTP_PASS}
      - SMTP_STARTTLS=false
      - SMTP_AUTHENTICATION=false

      - LDAP_ENABLED=true
      - LDAP_LABEL=${LDAP_LABEL}
      - LDAP_HOST=${LDAP_HOST}
      - LDAP_VERIFY_SSL=${LDAP_VERIFY_SSL}
      - LDAP_BIND_DN=${LDAP_BIND_DN}
      - LDAP_PASS=${LDAP_PASS}
      - LDAP_ALLOW_USERNAME_OR_EMAIL_LOGIN=${LDAP_ALLOW_USERNAME_OR_EMAIL_LOGIN}
      - LDAP_BASE=${LDAP_BASE}

      - GITLAB_PROJECTS_ISSUES=${GITLAB_PROJECTS_ISSUES}
      - GITLAB_PROJECTS_MERGE_REQUESTS=${GITLAB_PROJECTS_MERGE_REQUESTS}
      - GITLAB_PROJECTS_WIKI=${GITLAB_PROJECTS_WIKI}
      - GITLAB_PROJECTS_SNIPPETS=${GITLAB_PROJECTS_SNIPPETS}
      - GITLAB_PROJECTS_BUILDS=${GITLAB_PROJECTS_BUILDS}
      - GITLAB_PAGES_ENABLED=${GITLAB_PAGES_ENABLED}
      - GITLAB_MATTERMOST_ENABLED=${GITLAB_MATTERMOST_ENABLED}
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}
    volumes:
      - gitlab-runner-config-vol:/etc/gitlab-runner
      - gitlab-socket-vol:/var/run/docker.sock
# Redmineの設定
  redmine-db:
    image: sameersbn/postgresql:${POSTGRESQL_VERSION}
    restart: unless-stopped
    environment:
      - DB_USER=${REDMINE_DB_USER}
      - DB_PASS=${REDMINE_DB_PASS}
    volumes:
      - redmine-db-vol:/var/lib/postgresql
  redmine:
    image: sameersbn/redmine:${REDMINE_VERSION}
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    depends_on:
      - redmine-db
    environment:
      - TZ=Asia/Tokyo
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}

      - DB_ADAPTER=postgresql
      - DB_HOST=redmine-db
      - DB_PORT=5432
      - DB_USER=${REDMINE_DB_USER}
      - DB_PASS=${REDMINE_DB_PASS}
      - DB_NAME=redmine_production

      - REDMINE_PORT=${REDMINE_PORT}
      - REDMINE_HTTPS=false
      - REDMINE_RELATIVE_URL_ROOT=
      - REDMINE_SECRET_TOKEN=

      - REDMINE_SUDO_MODE_ENABLED=false
      - REDMINE_SUDO_MODE_TIMEOUT=15

      - REDMINE_CONCURRENT_UPLOADS=2

      - REDMINE_BACKUP_SCHEDULE=daily
      - REDMINE_BACKUP_EXPIRY=604800
      - REDMINE_BACKUP_TIME=02:00

      - SMTP_ENABLED=true
      - SMTP_DOMAIN=${SMTP_DOMAIN}
      - SMTP_HOST=${SMTP_HOST}
      - SMTP_PORT=${SMTP_PORT}
      - SMTP_USER=${SMTP_USER}
      - SMTP_PASS=${SMTP_PASS}
      - SMTP_STARTTLS=false
      - SMTP_AUTHENTICATION=false

      - LDAP_ENABLED=true
      - LDAP_LABEL=${LDAP_LABEL}
      - LDAP_HOST=${LDAP_HOST}
      - LDAP_VERIFY_SSL=${LDAP_VERIFY_SSL}
      - LDAP_BIND_DN=${LDAP_BIND_DN}
      - LDAP_PASS=${LDAP_PASS}
      - LDAP_ALLOW_USERNAME_OR_EMAIL_LOGIN=${LDAP_ALLOW_USERNAME_OR_EMAIL_LOGIN}
      - LDAP_BASE=${LDAP_BASE}

    ports:
      - "${REDMINE_PORT}:80"
    volumes:
      - redmine-vol:/home/redmine/data:Z
      - gitlab-vol:/home/git/data:ro

# Settings for nexus
  nexus:
    image: sonatype/nexus3
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    ports:
      - "${NEXUS_PORT}:8081"
    volumes:
      - nexus-vol:/nexus-data:Z
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}
      - JAVA_OPTS=-Duser.timezone=Asia/Tokyo -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8

# Settings for Jenkins
  jenkins:
    image: jenkinsci/blueocean
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    user: root
    ports:
      - '${JENKINS_PORT}:8080'
    volumes:
      - jenkins-vol:/var/jenkins_home:Z
      - /etc/localtime:/etc/localtime:ro
      - /etc/docker:/etc/docker:ro
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - JAVA_OPTS=-Duser.timezone=Asia/Tokyo -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
      - TZ=Asia/Tokyo
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}

# Settings for ELK
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION}
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}

      - discovery.type=single-node
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - ${ES_PORT}:9200
    volumes:
      - elastic-vol:/usr/share/elasticsearch/data

  logstash:
    image: docker.elastic.co/logstash/logstash:${ES_VERSION}
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}
      - discovery.type=single-node
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    depends_on:
      - elasticsearch
    ports:
      - ${LOGSTASH_PORT}:9600
    volumes:
      - logstash-vol:/usr/share/logstash

  grafana:
    image: grafana/grafana:${GRAFANA_VERSION}
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}
    depends_on:
      - elasticsearch
    ports:
      - ${GRAFANA_PORT}:3000
    volumes:
      - grafana-vol:/var/lib/grafana

# Settings for Communications
  mongo:
    image: mongo:4.0.16
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}
      - TZ=Asia/Tokyo
    volumes:
      - rocketchat-db-vol:/data
      - /etc/localtime:/etc/localtime:ro
    command: mongod --smallfiles --oplogSize 128 --replSet rs0 --storageEngine=mmapv1

  # initialization mongodb for create replicaset no need restart
  mongoinitreplica:
    image: mongo:4.0.16
    depends_on:
      - mongo
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}
      - TZ=Asia/Tokyo
    volumes:
      - /etc/localtime:/etc/localtime:ro
    command: 'mongo mongo/rocketchat --eval "rs.initiate({ _id: ''rs0'', members: [ { _id: 0, host: ''mongo:27017'' } ]})"'

  rocketchat:
    image: rocketchat/rocket.chat:${ROCKETCHAT_VERSION}
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    volumes:
      - rocketchat-vol:/app/uploads
      - /etc/localtime:/etc/localtime:ro
    depends_on:
      - mongoinitreplica
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}
      - ROOT_URL=${ROCKETCHAT_URL}
      - MONGO_URL=mongodb://mongo:27017/rocketchat
      - MONGO_OPLOG_URL=mongodb://mongo:27017/local?replSet=rs0
      - TZ=Asia/Tokyo
    ports:
      - ${ROCKETCHAT_PORT}:3000

  hubot:
    image: rocketchat/hubot-rocketchat:latest
    restart: unless-stopped
    dns:
      - ${DNS1}
      - ${DNS2}
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=${NO_PROXY}
      - ROCKETCHAT_URL=rocketchat:${ROCKETCHAT_PORT}
      - ROCKETCHAT_ROOM=GENERAL
      - ROCKETCHAT_USER=bot
      - ROCKETCHAT_PASSWORD=password
      - BOT_NAME=bot
      - EXTERNAL_SCRIPTS=hubot-help,hubot-seen,hubot-links,hubot-diagnostics,hubot-proxy-loader
      - TZ=Asia/Tokyo
    depends_on:
      - rocketchat
    labels:
      - "traefik.enable=false"
    volumes:
      - hubot-vol:/home/hubot
      - /etc/localtime:/etc/localtime:ro
    ports:
      - ${HUBOT_PORT}:8080

volumes:
  gitlab-redis-vol:
  gitlab-db-vol:
  gitlab-vol:
  gitlab-socket-vol:
  gitlab-runner-config-vol:
  redmine-db-vol:
  redmine-vol:
  nexus-vol:
  jenkins-vol:
  logstash-vol:
  elastic-vol:
  grafana-vol:
  rocketchat-db-vol:
  rocketchat-vol:
  hubot-vol:
```