DockerとNginxでWebサーバーを構築する【WordPress, GitLab, Redmine, Node.js】

DockerとNginxでWebサーバーを構築する【WordPress, GitLab, Redmine, Node.js】アイキャッチ 備忘録

概要

DockerとNginxで構築したWebサーバーの概略図

本記事では図のように、ホスト上のNginxがリバースプロキシとして稼働し、以下のアクセスを各アプリに振り分けるようなWebサーバーを構築する手順を解説します。

Nginxが振り分けるFQDN一覧
  • https://example.com
  • https://www.example.com
  • https://gitlab.example.com
  • https://redmine.example.com
  • https://node.example.com

動作確認環境:Ubuntu20.04

ざっくりした手順

手順は、サーバ準備とサーバ構築に分類してみましたが、本記事ではサーバ構築をメインに解説します。

サーバ準備
サーバ構築
  • Nginxをインストール・設定する
  • SSL化する
  • Docker・Docker-Composeをインストールする
  • 各アプリのコンテナを起動する
    • WordPress
    • GitLab
    • Redmine
    • Node.jsアプリ

サーバ準備

ここでは、サーバを準備する手順をざっくり紹介しています。DNS設定は手続きが完了してから、設定が反映されるまで時間(数時間〜72時間)がかかることがあるので、早めに済ませておくことをおすすめします。

VPSを準備する

さくらのVPSにアクセスして、2週間のお試し登録をする。

ドメインを取得する

お名前.comにアクセスして、何でもいいので、ドメインを取得する。1円のものでOK.

DNSを設定する

1.VPSのグローバルIPアドレスをメモする。
(さくらのVPSなら、コンソールから確認できる)

2.以下のようにDNS設定を行う。
(お名前.com Navi>ドメイン設定>DNS設定 から設定する)

ホスト名TYPEVALUE
example.comA1.でメモしたIPアドレス
www.example.comCNAMEexample.com
gitlab.example.comCNAMEexample.com
redmine.example.comCNAMEexample.com
node.example.comCNAMEexample.com
DNS設定

3.「example.com」の名前解決ができるか確認しておく。

サーバ構築

ここからは、実際に設定ファイルを作成したり、コマンドを叩いたりして、サーバを構築していきます。

Nginxをインストール・設定する

まずは、Nginxをインストールする

# apt-get準備
sudo apt-get install update
sudo apt-get install upgrade -y

# nginxをインストール
sudo apt-get install nginx

つぎに、Nginxの設定ファイルを編集して、各サブドメインでのアクセスを後で起動するコンテナに流すように設定する。

/etc/nginx/sites-availble/defaultを以下のように修正

# Default(WordPress) server configuration
#
server {
  listen 80;
  server_name www.nattoserver.net nattoserver.net;
    location / {
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Proto https;
      proxy_pass http://localhost:18080;
    }
}

# GitLab server configuration
#
server {
  listen 80;
  server_name gitlab.nattoserver.net;
    location / {
      proxy_set_header Host $http_host;
      proxy_pass http://localhost:31080;
    }
}

# Redmine server configuration
#
server {
  listen 80;
  server_name redmine.nattoserver.net;
    location / {
      proxy_set_header Host $http_host;
      proxy_pass http://localhost:3000;
    }
}

# nodeapp server configuration
#
server {
  listen 80;
  server_name node.nattoserver.net;
    location / {
      proxy_set_header Host $http_host;
      proxy_pass http://localhost:38080;
    }
}

SSL化する

各サーバ(FQDN)すべてをSSL化してしまいます。

# certbotをインストール
sudo apt-get install certbot python3-certbot-nginx

# SSL化する
sudo certbot --nginx -d nattoserver.net \ 
                     -d www.nattoserver.net \ 
                     -d gitlab.nattoserver.net \ 
                     -d redmine.nattoserver.net \ 
                     -d node.nattoserver.net

Docker・Docker-Composeをインストールする

公式サイト(Ubuntuの場合):https://docs.docker.com/engine/install/ubuntu/

# docker(スクリプトでインストール)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo rm get-docker.sh

# docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# バージョンは適宜変更

# docker-composeコマンドの実行権限を変更する
sudo chmod +x /usr/local/bin/docker-compose

各アプリのコンテナを起動する

基本的には、各アプリに対して以下のことをやるだけです。

  • 作業フォルダを作成
  • docker-compose.ymlを作成
  • コンテナ起動

環境変数を使用したり、しなかったり、ポート番号などは、ご使用の環境に合わせて変更してみてください。
※ポート番号を変更した場合は、忘れずにNginxの設定ファイルも変更してください。

WordPress

WordPress-docker

作業ディレクトリを作成して、環境変数を作成

# 作業ディレクトリを作成して、以後ここで作業
sudo mkdir /srv/wordpress
cd /srv/wordpress

# docker-compose.yml内で使用する環境変数を.envファイルに記載しておく
sudo touch .env
MYSQL_ROOT_PASSWORD=AAA
DB_NAME=XXX
DB_USER=YYY
DB_PASSWORD=ZZZ

docker-compose.ymlを作成して、中身を編集

# docker-compose.ymlを作成して、以下のようにする
sudo touch docker-compose.yml
version: "3"
services:
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
      MYSQL_DATABASE: $DB_NAME
      MYSQL_USER: $DB_USER
      MYSQL_PASSWORD: $DB_PASSWORD
    ports:
      - '13306:3306'
    volumes:
      - db_data:/var/lib/mysql
    command: --port 13306 # 3306, 33060 以外の場合は必要(https://qiita.com/ryuji-oda/items/c3ed1b86fe0c1f2b9058)

  wordpress:
    container_name: wordpress
    image: wordpress:php8.0-fpm
    restart: always
    depends_on:
      - db
    expose:
      - '9000'
    environment:
      WORDPRESS_DB_HOST: db:13306
      WORDPRESS_DB_NAME: $DB_NAME
      WORDPRESS_DB_USER: $DB_USER
      WORDPRESS_DB_PASSWORD: $DB_PASSWORD
      WORDPRESS_CONFIG_EXTRA: "define('WP_HOME','https://example.com'); define('WP_SITEURL','https://example.com');"
    volumes:
      - ./wordpress_data:/var/www/html
    links:
      - db

  wp-nginx:
    image: nginx:1.21
    restart: always
    depends_on:
      - wordpress
    ports:
      - '18080:80'
    volumes:
      - ./nginx:/etc/nginx/conf.d
      - ./logs/nginx:/var/log/nginx
      - ./wordpress_data:/var/www/html
MySQLのポートフォワーディングについて備考

3306, 33060 以外の場合は必要`command: –port 13306`のようにしてあげないと、接続できなかった。
参考:https://qiita.com/ryuji-oda/items/c3ed1b86fe0c1f2b9058
※今のところ公式サイトで該当箇所が見つからない

コンテナ内で使用するNginx設定ファイルを作成する

# コンテナ内で使用するnginx設定ファイルを作成
sudo mkdir /etc/wordpress/nginx # マウントするディレクトリ内に配置する
sudo touch default.conf
server {
  listen 80; 
  server_name _;
 
  root /var/www/html;
  index index.php index.html index.htm;
       
  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;
  #client_max_body_size 128M;
 
  location / {
    try_files $uri $uri/ /index.php;
  }
 
  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass wordpress:9000; # ワードプレス自体のコンテナ名:ポート番号
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
  }
}

コンテナを起動する

# 起動
docker-compose up -d

コンテナが起動したら、「https://example.com」もしくは「https://www.example.com」にアクセスすれば、ワードプレスの初期画面が表示されるはずです。

※mb4対応はまた別途(ToDo)

GitLab

Gitlab-docker

作業ディレクトリを作成する。

# 作業ディレクトリを作成して、以後ここで作業
sudo mkdir /srv/gitlab
cd /srv/gitlab

docker-compose.ymlを作成して、中身を編集

# docker-compose.ymlを作成して、以下のようにする
sudo touch docker-compose.yml
version: "3"
services:
  gitlab:
    image: 'gitlab/gitlab-ce:latest' # ee版を使ってもいい
    restart: always
    hostname: 'gitlab.nattoserver.net'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://gitlab.nattoserver.net'
        nginx['listen_port'] = 80
        nginx['listen_https'] = false
        letsencrypt['enable'] = false
    ports:
      - '31080:80'
    volumes:
      - './gitlab/config:/etc/gitlab'
      - './gitlab/logs:/var/log/gitlab'
      - './gitlab/data:/var/opt/gitlab'
  gitlab-runner:
    image: 'gitlab/gitlab-runner:latest'
    restart: always
    volumes:
      - './gitlab-runner/config:/etc/gitlab-runner'
      - '/var/run/docker.sock:/var/run/docker.sock'

このままdockerを起動すると、エラーが出るので、config.tmlファイルを作成しておく。

# こんなエラーが出る
gitlab-runner_1  | ERROR: Failed to load config stat /etc/gitlab-runner/config.toml: no such file or directory  builds=0
# config.tomlファイルを作っておく
sudo mkdir /etc/gitlab-runner
sudo touch /etc/gitlab-runner/config.toml

コンテナを起動する

# 起動
docker-compose up -d

この状態で、「https://gitlab.example.com」にアクセスすると、ログイン画面が表示されるが、rootのパスワードも分からない状態である。

そのため、コンテナに接続して、直接rootのパスワードを編集する。

# コンテナに接続する
sudo docker exec -it [コンテナ名] bash
# コンテナ名は`sudo docker ps`したときのNAMESでわかる

Railsコンソールを起動する

# Railsコンソールを起動して接続
gitlab-rails console -e production # 時間がかかるので待つ

rootのパスワードを変更する

# rootを取得
user = User.find(1)

# パスワードを設定
user.password = 'Xxx'
user.password_confirmation = 'Xxx'

# 保存
user.save!

# Railsコンソール終了
exit

再度「https://gitlab.example.com」に接続して、設定したパスワードでログインできるはず。

その他の基本設定
# 対話型の登録フローを開始
sudo docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register

# Enter the GitLab instance URL (for example, https://gitlab.com/):
[GitLabのトップページ]

# Enter the registration token:
[CI/CDページで取得したトークン]

# Enter a description for the runner:
[分かりやすい名前] 後で変更可能

# Enter tags for the runner (comma-separated):
[ランナーに付与したいタグ]]
ちなみに、何も入力せずエンターで良い。後で変更可能

# Enter an executor: custom, docker, docker-ssh, shell, ssh, kubernetes, parallels, virtualbox, docker+machine, docker-ssh+machine:
docker

# Enter the default Docker image (for example, ruby:2.6):
ruby:2.6

プロジェクト>設定>CI/CD>一般のパイプライン の `CI/CD configuration file`にciファイルの名前を設定しておく。

※前提として、「Gmailの2段階認証プロセスを有効にする」「アプリパスワードを設定する」は済ませておくこと。

docker-compose.ymlファイルにSMTPサーバの情報を記載して、コンテナを再起動すれば完了する。

version: '3'
services:
  gitlab:
    image: 'gitlab/gitlab-ce:latest'
    restart: always
    hostname: 'gitlab.nattoserver.net'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://gitlab.nattoserver.net'
        nginx['listen_port'] = 80
        nginx['listen_https'] = false
        letsencrypt['enable'] = false
        gitlab_rails['smtp_enable'] = true
        gitlab_rails['smtp_address'] = "smtp.gmail.com"
        gitlab_rails['smtp_port'] = 587
        gitlab_rails['smtp_user_name'] = "<your_user_name>@gmail.com"
        gitlab_rails['smtp_password'] = "<アプリパスワード16桁>"
        gitlab_rails['smtp_domain'] = "smtp.gmail.com"
        gitlab_rails['smtp_authentication'] = "login"
        gitlab_rails['smtp_enable_starttls_auto'] = true
        gitlab_rails['smtp_tls'] = false
        gitlab_rails['smtp_openssl_verify_mode'] = 'peer'
    ports:
      - '31080:80'
    volumes:
      - './gitlab/config:/etc/gitlab'
      - './gitlab/logs:/var/log/gitlab'
      - './gitlab/data:/var/opt/gitlab'
  gitlab-runner:
    image: 'gitlab/gitlab-runner:latest'
    restart: always
    volumes:
      - './gitlab-runner/config:/etc/gitlab-runner'
      - '/var/run/docker.sock:/var/run/docker.sock'

Redmine

Redmine-docker

作用ディレクトリを作成する

# 作業ディレクトリを作成して、以後ここで作業
sudo mkdir /srv/gitlab
cd /srv/gitlab

docker-compose.ymlを作成して、中身を編集する

# docker-compose.ymlを作成して、以下のようにする
sudo touch docker-compose.yml
version: '3'
services:
  redmine:
    image: redmine:4.2.2   
    restart: always
    ports:
      - 3000:3000
    volumes:
      - ./data/plugins:/usr/src/redmine/plugins
      - ./data/themes:/usr/src/redmine/public/themes
    environment:
      REDMINE_DB_MYSQL: db
      REDMINE_DB_PASSWORD: password
      REDMINE_SECRET_KEY_BASE: supersecretkey
      REDMINE_DB_ENCODING: utf8mb4 # DBの文字コードを設定(Unicode対応)
    depends_on:
      - db

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: redmine
    ports:
      - 3306:3306
    volumes:
      - ./mysql:/var/lib/mysql
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci # Unicode対応
Unicode対応が大事な話

Unicode対応しておかないと、日本語のプロジェクトを作成しようとしたりすると、内部エラーが発生する。
※もし、日本語対応せずにコンテナ起動してしまった場合は、バインドマウントしたホストPC側のディレクトリ削除(上記の`./data`に相当)と、コンテナ削除をしてから、再度コンテナを立ち上げること。

コンテナを起動する

# 起動
docker-compose up -d

「https://redmine.example.com」にアクセスして、初期設定を済ませる。

Node.jsアプリ

Nodejs-docker

Node.jsアプリだけ、Dockerfileを作成して、オリジナルのアプリを動かすDockerイメージを作成してみた。

作業ディレクトリを作成する

sudo mkdir ~/workDockerfile
sudo mkdir ~/workDockerfile/nodeapp
cd ~/workDockerfile/nodeapp

サンプリのnodeアプリを作っていく

# 必要なものをインストール
sudo apt-get install node npm

# nodeアプリを作成
sudo npm init -y # package.jsonが作成される

作成されるpackage.jsonに以下のように修正を加え、npm installしたときにexpressをインストールするようにする。

  "name": "nodeapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC", //★「,」追加
  "dependencies": { //★追加
    "express": "^4.16.1"
  }
}

アプリのメインのソースファイルを作成する

sudo touch index.js
const express = require('express');

// Constants
const PORT = 8080;
const HOST = '0.0.0.0';

// App
const app = express();
app.get('/', (req, res) => {
  res.send('Hello World');
});

app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

Dockerfileを作成して、中身を編集する

sudo touch Dockerfile
# ベースイメージをpullしてくる
# https://hub.docker.com/_/node?tab=description&page=1&ordering=last_updated
FROM node:10

# アプリディレクトリを作成し。以降ここで作業する
#(コンテナ側のディレクトリを示している)
WORKDIR /usr/src/app

# アプリの依存関係定義ファイルをインストールする
# ワイルドカードを使用して、package.json と package-lock.json の両方が確実にコピーされるようにする
# ホストPC コンテナ側 の順で記述する
COPY package*.json ./

# パッケージをインストールする
RUN npm install

# アプリケーションのソースをバンドルする
# (今でいうと、index.jsをコピーしている)
COPY . .

# コンテナの8080ポートにマッピングするようdockerに通知する
EXPOSE 8080

# nodeアプリを実行する
CMD [ "node", "index.js" ]

Dockerビルド時に、無駄なファイルを含めないようにする

sudo touch .dockerignore
node_modules
npm-debug.log

現時点で、ディレクトリはこんな感じ

~/workDockerfile/nodeapp
                      ├── Dockerfile
                      ├── index.js
                      └── package.json

Dockerイメージをビルドして、コンテナ起動までしてしまう

# ビルドする
docker build . -t hondakenya/node-sample:1.0

# ビルドされたイメージを確認する
docker images
# REPOSITORY                      TAG       IMAGE ID       CREATED         SIZE
# hondakenya/node-sample          1.0       34efb0bb8631   4 minutes ago   914MB
# node                            10        28dca6642db8   4 months ago    910MB

# コンテナを起動する
docker run -p 38080:8080 -d hondakenya/node-sample:1.0

# アクセスして動作確認
curl localhost:38080
# Hello World

ちなみに、docker-compose.ymlだとこうなる。

version: "3"

services:
  node:
    image: hondakenya/node-sample:1.0
    restart: always
    ports:
      - 38080:8080
イメージをDocker Hubにアップロードする

前提:Docker Hubアカウントを作成しておく

# Docker Hubにログインする
docker login

# イメージにタグを付ける
# 命名規則 → <Docker ID>/<イメージ名>:<タグ名>
docker image tag node-sample hondakenya/node-sample:1.0 

# イメージを確認する
docker images
# REPOSITORY               TAG       IMAGE ID       CREATED             SIZE
# hondakenya/node-sample   1.0       34efb0bb8631   About an hour ago   914MB
# node                     10        28dca6642db8   4 months ago        910MB

# プッシュする
docker push hondakenya/node-sample:1.0

やり残していること

  • 軽量なDockerイメージを選択すること
  • 各コンテナのログファイルをホスト側にバインドマウントすること
  • ワードプレスのutfmb4対応
  • これらをGit管理すること

コメント

タイトルとURLをコピーしました