20200726のdockerに関する記事は15件です。

DockerでFlask+Gunicorn+Nginxの環境構築

以前、php-fpm+Nginxの環境をDockerで作りましたが、今回はGunicorn+Nginxで環境を作ります。

Gunicorn

6a517679405a1702fcdf55bf2cebf237-png.png

Gunicorn(Green Unicorn)はWSGI HTTPサーバです。GunicornはRubyのUnicornプロジェクトから移行してきたpre-fork workerモデル(HTTPリクエストを受け取った時に、事前に用意した子プロセスで処理するモデル)です。
同じレイヤーのアプリでPython系では、これ以外に(使ったことはないですが、)uWSGIというものもあります。
今回はFlaskアプリを作りますが、GunicornがFlaskアプリを実行するという形になります。

Nginx

202004c01.png

NginxはHTTPサーバ、リバースプロキシサーバ、メールプロキシサーバ、TCP/UDPプロキシサーバのサービスを提供するOSSです。
同じレイヤーのアプリでApacheがありますが、ApacheよりNginxの方が高速に動かすことができます。
クライアントからのHTTPリクエストは、Nginxが受け、それをGunicornに中継します。

システム構成

コンテナは下記のように立てます。
コンテナ構成図_gunicorn (1).png

外部からはNginxしかアクセスできないようにしています。
以前、Nginxとphp-fpm間の通信では、TCPソケット通信しか試さなかったので、今回は
NginxとGunicorn間は、TCPソケット通信とUNIXドメインソケット通信の二通り試しました。

非常に勉強になる他者様の記事を参考に書いていきます。

TCPソケット通信

正しくはINETドメインと呼ぶようです。
こちらは「異なるマシンで動作しているプロセス間の通信を行うためのソケット」です。
ソケットは、OSI参照モデルのセッション層のレイヤーにあたるもので、※通信はIPアドレスとポート番号によって行います。(※HTTPではありません。)
そのため、ネットワーク上でマシンを超えたプロセス間通信が行えます。また、他にもUNIXドメインソケットとは違い、1台のプロキシサーバから複数台のWebアプリケーションサーバに通信を割り当て、負荷分散をさせたり、WebサーバとWebアプリケーションサーバを別のマシンに置いても使えるというメリットがあります。

また、これは所感ですが、TCPソケットの場合、コンテナにポートを開けることで、Nginxを介さずに動作確認できるのもあり、エラーが起きたときに原因の確認がしやすいです。

UNIXドメインソケット

こちらは「同じマシン内で動作しているプロセス間の通信を行うためのソケット」です。
マシン内にbindファイルを用意し、WebサーバとWebアプリケーションサーバをこのファイルを介して通信をします。そのため、この通信は同じマシン内でしか行なえません。代わりに、ファイルの書き込み・読み込みで通信ができるため、TCPソケットによる通信より速いです。また注意点として、この通信をサポートしているサービスが限られています。詳しくは、他者様の記事

実装

今回はDocker周り、Nginx周りとgunicorn・flask周りの部分を残します。
まずはcomposeファイルから

docker-compose.yml
version: '3'

services:
    web:
        build: 
          context: ./web
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - ./web/public:/etc/nginx/public
          - ../ssl/certs/:/etc/pki/tls/certs/
          - ../ssl/private/:/etc/pki/tls/private/
          - ./gunicorn_socket:/tmp/gunicorn_socket
        depends_on:
          - app
        container_name: web
        restart: always
        networks:
          - network

    app:
        build: 
          context: ./app
        volumes:
          - ./app:/var/www/
          - ./gunicorn_socket:/tmp/gunicorn_socket
        depends_on:
          - db
        container_name: app
        ports:
            - 9876:9876
        networks:
          - network

volumes:
    db_data: {}

networks:
    network:
      driver: bridge

WebコンテナがNginxのコンテナ、AppコンテナがGunicorn+Flaskのコンテナです。

volumes:
  - ./gunicorn_socket:/tmp/gunicorn_socket

この部分で、UNIXドメインソケットの通信で使うソケットファイルを出力するディレクトリをマウントします。
TCPソケットを使う場合はここの記述は不要です。

ports:
  - 9876:9876

Appコンテナは9876ポートを開けています。
これはAppコンテナ内で9876ポートで立てているGunicornに外部からアクセスできるようにしているからです。
こちらがなくとも、WebコンテナはAppコンテナと通信できます。UNIXドメインソケットを使う場合はここの記述不要です。
本番環境で使う場合も不要なポートを開けるのは避けた方がいいので、ここの記載はやめた方がいいです。

Nginxコンテナ

Dockerfileは下記です。

FROM nginx:latest

COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./server.conf /etc/nginx/conf.d/server.conf


CMD ["nginx", "-g", "daemon off;"]

build時に、コピーするファイルは下記です。

nginx.conf
user nginx;

worker_processes auto;
pid /var/run/nginx.pid;

events{
    worker_connections 512;
    multi_accept on;
    use epoll;
}

http {
    charset UTF-8;
    server_tokens off;

    include /etc/nginx/mime.types;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ssl_protocols TLSv1.1 TLSv1.2;

    default_type  text/html;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    include /etc/nginx/conf.d/server.conf;
}

server.conf
upstream app {
    # UNIXドメインソケットを使う場合
    server unix:/tmp/gunicorn_socket/gunicorn_flask.sock fail_timeout=0;

    # TCPソケットを使う場合
    server app:9876 fail_timeout=0;
}

server {
        listen 80;
        server_name  localhost;

        root /var/www/public;

        access_log /var/log/nginx/access.log;
        error_log  /var/log/nginx/error.log;

        location / {
            try_files $uri @flask;
        }

        location @flask {
            proxy_pass_request_headers on;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_redirect off;
            proxy_pass http://app;
        }
}

upstreamという部分で、UNIXドメインソケットか、TCPソケットを使うかを選択します。
※使わない方をコメントアウトして使ってください。

Gunicorn+Flaskコンテナ

Dockerfileは下記です。

FROM python:3.8
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apt update -y

RUN mkdir -p /var/www
COPY ./requirements.txt /var/www
RUN pip install -r /var/www/requirements.txt

COPY ./flask_app.py /var/www
COPY ./gunicorn.py /var/www

WORKDIR /var/www

CMD ["gunicorn", "flask_app:app", "--config", "/var/www/gunicorn.py" ]
requirements.txt
Flask==1.1.2
gunicorn==20.0.4

GunicornとFlaskはpipでinstallします。
今回、Gunicornはsystemdサービスのものは使いません。(ネットではsystemdサービスを使う方法が多いですが、)
やることは同じなので、お好きな方を選択して使ってください。
あとは、flaskアプリのファイルとgunicornのconfigファイルを用意します。

flask_app.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World'
gunicorn.py
import os

# UNIXドメインソケット
socket_path = 'unix:/tmp/gunicorn_socket/gunicorn_flask.sock'
# TCPソケット
socket_path = '0.0.0.0:' + str(os.getenv('PORT', 9876))
bind = socket_path

# Debugging
reload = True

# Logging
accesslog = '-'
#loglevel = 'info'
loglevel = 'debug'
logfile = './log/app.log'
logconfig = None

# Proc Name
proc_name = 'Infrastructure-Practice-Flask'

# Worker Processes
workers = 2
worker_class = 'sync'

gunicorn.pyのsocket_pathでどっちの通信を受け付ける設定にするかを指定します。こちらも両方書いているので、どちらかをコメントアウトして使ってください。

また、補足ですが、コンテナを使うとエラーが起きた時に原因がわかりにくいことが多いです。

$ docker logs -f ${コンテナ名}

でコンテナのログを見れます。
また、Gunicornを使ってのFlaskアプリの起動は

$ gunicorn flask_app:app --config /var/www/gunicorn.py

で行っていますので、コンテナの起動に失敗している方は一度コンテナを使わない環境で動作確認された方が解決が早いかもしれません。

以上の設定で下記のコマンドでbuild+コンテナ起動をさせますと

$ docker-compose build
$ docker-compose up -d

UNIXドメインソケットを使われる方は
docker-compose.ymlのディレクトリに、gunicorn_socketというディレクトリができています。ここにgunicorn_flask.sockというファイルができており、通信できます。

エラーの確認がしやすい、負荷分散できることを考えると、個人的にはやはりTCPソケットですかね。
皆さんはどっちがいいとかありますか?

参考

調べなきゃ寝れない!と調べたら余計に寝れなくなったソケットの話

INETドメインとUNIXドメイン

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

基本的なDockerコマンドメモ

Dockerイメージ関係

イメージを取得する

タグを指定しなかった場合、デフォルトではlatestタグのイメージが取得されます。

$ docker pull [イメージ名]

Dockerfileからイメージをビルドする

キャッシュを無効化する場合は、--no-chacheオプションを追加

$ docker build -t [生成するイメージ名]:[タグ名を指定] [ビルドコンテキストを指定]

Dockerfileという名前のファイルがビルドコンテキストに入っていない場合は、以下のように-fオプションを追加してパスを指定

$ docker build -f [Dockerfile名(パスを指定)] [ビルドコンテキストを指定]

ダウンロード済みのイメージ一覧を表示する

$ docker images 

 // もしくは、

$ docker image list

イメージの詳細情報を表示する

$ docker inspect [イメージ名]

イメージを削除する

もし既に、削除対象のイメージからコンテナが作成されている場合は、そのコンテナの削除後でないとイメージを削除できません。
-f オプションを付けると強制削除が可能)

$ docker rmi [イメージ名 or イメージID]

  // もしくは、

$ docker image rm [イメージ名 or イメージID]

イメージを一括削除する

イメージを作成し過ぎてしまって、不要なものをまとめて削除したい時に便利なコマンドです。

$ docker image prune

コンテナ関係

DockerHubからイメージを取得して、コンテナを起動する

$ docker run [イメージ名]:[タグ名]

→タグ名は、主にイメージのバージョン

docker runコマンドは、以下の3つのコマンドを1度にまとめて実行するコマンドです。

 ①docker pull:イメージの取得
 ②docker create:コンテナの作成
 ③docker start:コンテナの起動

オプション:

-d :プロセスをバックグラウンドで実行
-it:コンテナのシェルに接続する時に必要なオプション
--name [コンテナ名]:コンテナ名を付ける
--rm:コンテナを停止すると、そのままコンテナが削除されるようにする

コンテナを再起動する

$ docker restart [コンテナ名 or コンテナID]

コンテナを一時停止/再開する

  //コンテナの一時停止
$ docker pause [コンテナ名 or コンテナID]

  //コンテナの再開
$ docker unpause [コンテナ名 or コンテナID]

コンテナを停止する

$ docker stop [コンテナ名 or コンテナID]

コンテナを削除する

コンテナを削除するには、docker stopでコンテナを停止する必要があります。
もしくは、下記コマンドに-fオプションを加えることで強制削除することも可能です。

$ docker rm [コンテナ名 or コンテナID]

オプション:
-f:コンテナが停止していなくても強制削除する

コンテナを一括削除する

コンテナを作成し過ぎてしまって、不要なものをまとめて削除したい時に便利なコマンドです。

$ docker container prune

コンテナ一覧を表示する

現在実行しているコンテナを一覧表示します。

$ docker ps

オプション:
-a:現在実行されていないコンテナも表示

DockerHubへのプッシュ

DockerHubにログイン

$ docker login

DockerHubにおけるタグ付けのルール

[Docker ID]/[イメージ名]:[タグ名]

DockerHubにプッシュ

$ docker push [Docker ID]/[イメージ名 ]:[タグ名]

コンテナのシェルに接続

イメージからコンテナを作成・起動してコンテナに接続

$ docker run -it [イメージ名 or イメージID] bash
  // ※シェルがbashの場合

ホストのファイルシステムをコンテナにマウントする時は、-vオプションを使用します。

$ docker run -it -v [ホストのマウント元のパス]:[コンテナのマウント先のパス] [イメージ名 or イメージID] bash

更に、コンテナに接続するユーザを指定する時は-uオプションを使用します。

例)ホストユーザーでコンテナに接続する場合

$ docker run -it -u $(id -u):$(id -g) -v [ホストのマウント元のパス]:[コンテナのマウント先のパス] [イメージ名 or イメージID] bash

既にあるコンテナに接続

$ docker exec -it [コンテナ名 or コンテナID] bash
  // ※シェルがbashの場合

コンテナから抜ける時は、以下のいずれかを実行
(よく利用されるのはexit)

①exitコマンド
    → コンテナを動かしているプロセスを切ってコンテナから出る

②Control + q + p(detach)
    → コンテナを動かしているプロセスを残してコンテナから出る

ホストマシン⇆コンテナ間でのコピー

ホストマシンのファイルをコンテナ内にコピー

ホストマシン→コンテナ

$ docker cp [ホスト上のコピーしたいファイルのパス]  [コンテナ名 or コンテナID]:[コピー先のパス]

コンテナ内のファイルをホストマシンにコピー

コンテナ→ホストマシン

$ docker cp [コンテナ名 or コンテナID ]:[コンテナ上のコピーしたいファイルのパス]  [コピー先のパス]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MacでDockerコンテナ上にGitLabを構築する

やろうとした理由

前回、Docker上にRedmineを入れたので、その流れでGitLabもやってみようと。

事前確認

1. Dockerイメージを確認する

Macのバージョンと、Dockerのバージョンは割愛。(前回やったから)

$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
mariadb                latest              8075b7694a2d        40 hours ago        407MB
redmine                latest              809721a71330        3 days ago          544MB
hybridcloudibm/wexdg   latest              b482197b4310        2 years ago         5.83GB

2. 起動中のDockerコンテナを確認する

Redmineとmariadbが動いている状態。

$ docker ps -a
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS                       PORTS                                      NAMES
e9c787057ae4        redmine                   "/docker-entrypoint.…"   26 hours ago        Up 26 hours                  0.0.0.0:3000->3000/tcp                     redmine
8619aa4a4c36        mariadb                   "docker-entrypoint.s…"   26 hours ago        Up 26 hours                  3306/tcp                                   redmine-db
c522c16cdb88        hybridcloudibm/wexdg      "/opt/ibm/wex/sbin/e…"   22 months ago       Exited (255) 20 months ago   8000/tcp, 0.0.0.0:443->443/tcp, 9080/tcp   wex-d-g

3. docker-compose.ymlファイルを作成する

これがキモなので。

docker-compose.yml
version: '3.8'
services:
  gitLab:
    container_name: gitlab
    image: gitlab/gitlab-ce:latest
    ports:
     - "80:80"
    volumes:
     - ./GitLab/srv/gitlab/config:/etc/gitlab
     - ./GitLab/srv/gitlab/logs:/var/log/gitlab
     - ./GitLab/srv/gitlab/data:/var/opt/gitlab

DockerでGitLabを立ち上げる(docker-compose)

1. docker-composeコマンドを実行する

レッツゴー。

$ docker-compose up -d
Pulling gitLab (gitlab/gitlab-ce:latest)...
latest: Pulling from gitlab/gitlab-ce
6aa38bd67045: Pull complete
981ae4862c05: Pull complete
5bad8949dcb1: Pull complete
ca9461589e70: Pull complete
79b3488bd514: Pull complete
da7621effa84: Pull complete
c658ceb6fba5: Pull complete
1b64275b397c: Pull complete
204e4d0ddbcb: Pull complete
05f5900b030f: Pull complete
Digest: sha256:e7d76ace1548682d98be2a7f5863d5db147a6f5a3bf33339e8abd00a81f9dd08
Status: Downloaded newer image for gitlab/gitlab-ce:latest
Creating gitlab ... done

2. dockerイメージを確認する

$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
mariadb                latest              8075b7694a2d        40 hours ago        407MB
gitlab/gitlab-ce       latest              a7d268d6398b        2 days ago          1.91GB
redmine                latest              809721a71330        3 days ago          544MB
hybridcloudibm/wexdg   latest              b482197b4310        2 years ago         5.83GB

3. 起動中のDockerコンテナを確認する

$ docker ps -a
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS                             PORTS                                      NAMES
87b7c0d54971        gitlab/gitlab-ce:latest   "/assets/wrapper"        20 seconds ago      Up 16 seconds (health: starting)   22/tcp, 443/tcp, 0.0.0.0:80->80/tcp        gitlab
e9c787057ae4        redmine                   "/docker-entrypoint.…"   26 hours ago        Up 26 hours                        0.0.0.0:3000->3000/tcp                     redmine
8619aa4a4c36        mariadb                   "docker-entrypoint.s…"   26 hours ago        Up 26 hours                        3306/tcp                                   redmine-db
c522c16cdb88        hybridcloudibm/wexdg      "/opt/ibm/wex/sbin/e…"   22 months ago       Exited (255) 20 months ago         8000/tcp, 0.0.0.0:443->443/tcp, 9080/tcp   wex-d-g

4. ブラウザで起動したGitLabを確認する

http://localhost:80で開きます。

20200726_IMG_0000.png

docker越しに、GitLabの構成情報バックアップコマンドを実行

GitLabで本当にやりたかったのはこっち。
CREATIONLINEさんの記事にあったコマンドを自分で打って動きを確認しておきたかった。

1. /etc直下を確認

$ docker exec -it 87b7c0d54971 ls -l /etc
total 444
drwxr-xr-x  3 root root    4096 Apr 12  2016 X11
-rw-r--r--  1 root root    3028 Jun 19 18:25 adduser.conf
drwxr-xr-x  1 root root    4096 Jul 23 21:12 alternatives
drwxr-xr-x  1 root root    4096 Jun 19 18:26 apt
-rw-r--r--  1 root root    2188 Aug 31  2015 bash.bashrc
drwxr-xr-x  2 root root    4096 Jun 19 18:25 bash_completion.d
-rw-r--r--  1 root root     367 Jan 27  2016 bindresvport.blacklist
drwxr-xr-x  2 root root    4096 Apr 12  2016 binfmt.d
drwxr-xr-x  3 root root    4096 Jul 23 21:12 ca-certificates
-rw-r--r--  1 root root    5678 Jul 23 21:12 ca-certificates.conf
drwxr-xr-x  2 root root    4096 Jun 19 18:25 cron.daily
drwxr-xr-x  2 root root    4096 Jun 19 18:25 cron.weekly
drwxr-xr-x  3 root root    4096 Apr 12  2016 dbus-1
-rw-r--r--  1 root root    2969 Nov 10  2015 debconf.conf
-rw-r--r--  1 root root      12 Apr 30  2015 debian_version
drwxr-xr-x  1 root root    4096 Jul 23 21:12 default
-rw-r--r--  1 root root     604 Jul  2  2015 deluser.conf
drwxr-xr-x  3 root root    4096 Jun 19 18:25 dhcp
drwxr-xr-x  1 root root    4096 Jun 19 18:25 dpkg
-rw-r--r--  1 root root      96 Jun 19 18:25 environment
-rw-r--r--  1 root root      37 Jun 19 18:25 fstab
-rw-r--r--  1 root root    2584 Feb 18  2016 gai.conf
drwxrwxr-x 11 root root     352 Jul 26 09:16 gitlab

〜省略〜

drwxr-xr-x  2 root root    4096 Apr 12  2016 udev
drwxr-xr-x  3 root root    4096 Jul 23 21:12 ufw
drwxr-xr-x  2 root root    4096 Jul 23 21:12 vim
-rw-r--r--  1 root root    4942 Apr  8  2019 wgetrc
drwxr-xr-x  3 root root    4096 Apr 12  2016 xdg

2. /etc/gitlab直下を確認

$ docker exec -it 87b7c0d54971 ls -l /etc/gitlab
total 152
-rw------- 1 root root  18892 Jul 26 09:25 gitlab-secrets.json
-rw------- 1 root root 110359 Jul 26 09:16 gitlab.rb
-rw------- 1 root root    227 Jul 26 09:16 ssh_host_ecdsa_key
-rw-r--r-- 1 root root    179 Jul 26 09:16 ssh_host_ecdsa_key.pub
-rw------- 1 root root    411 Jul 26 09:16 ssh_host_ed25519_key
-rw-r--r-- 1 root root     99 Jul 26 09:16 ssh_host_ed25519_key.pub
-rw------- 1 root root   1675 Jul 26 09:16 ssh_host_rsa_key
-rw-r--r-- 1 root root    399 Jul 26 09:16 ssh_host_rsa_key.pub
drwxr-xr-x 2 root root     64 Jul 26 09:16 trusted-certs

3. GitLab構成情報のバックアップ取得

何か出たけど、ちゃんとバックアップは取れていそう。

$ docker exec -it 87b7c0d54971 tar cvzf /etc/20200726backup.tar.gz /etc/gitlab
tar: Removing leading `/' from member names
/etc/gitlab/
/etc/gitlab/trusted-certs/
/etc/gitlab/ssh_host_rsa_key
/etc/gitlab/ssh_host_ed25519_key
/etc/gitlab/gitlab-secrets.json
/etc/gitlab/ssh_host_ecdsa_key.pub
/etc/gitlab/ssh_host_rsa_key.pub
/etc/gitlab/ssh_host_ed25519_key.pub
/etc/gitlab/gitlab.rb
/etc/gitlab/ssh_host_ecdsa_key

4. 作成したtarファイルをローカルにコピー

$ docker cp 87b7c0d54971:/etc/20200726backup.tar.gz ./20200726backup2.tar.gz
$ 
$ ls -l
total 88
-rw-r--r--  1 hogehoge  staff  43914  7 26 21:28 20200726backup2.tar.gz
drwxr-xr-x  3 hogehoge  staff     96  7 26 18:16 srv

5. アプリケーションデータのバックアップ取得

データが入っていないのに、結構時間がかかった。
Warningは、以前のバックアップが存在しないから?
時間はUTCなので、9時間ずれています。

$ docker exec -it 87b7c0d54971 gitlab-rake gitlab:backup:create
2020-07-26 12:50:56 +0000 -- Dumping database ... 
Dumping PostgreSQL database gitlabhq_production ... [DONE]
2020-07-26 12:52:37 +0000 -- done
2020-07-26 12:52:37 +0000 -- Dumping repositories ...
2020-07-26 12:52:39 +0000 -- done
2020-07-26 12:52:39 +0000 -- Dumping uploads ... 
2020-07-26 12:52:39 +0000 -- done
2020-07-26 12:52:39 +0000 -- Dumping builds ... 
2020-07-26 12:52:39 +0000 -- done
2020-07-26 12:52:39 +0000 -- Dumping artifacts ... 
2020-07-26 12:52:39 +0000 -- done
2020-07-26 12:52:39 +0000 -- Dumping pages ... 
2020-07-26 12:52:39 +0000 -- done
2020-07-26 12:52:39 +0000 -- Dumping lfs objects ... 
2020-07-26 12:52:39 +0000 -- done
2020-07-26 12:52:39 +0000 -- Dumping container registry images ... 
2020-07-26 12:52:39 +0000 -- [DISABLED]
Creating backup archive: 1595767959_2020_07_26_13.2.1_gitlab_backup.tar ... done
Uploading backup archive to remote storage  ... skipped
Deleting tmp directories ... done
done
done
done
done
done
done
done
Deleting old backups ... skipping
Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data 
and are not included in this backup. You will need these files to restore a backup.
Please back them up manually.
Backup task is done.
$ 
$ docker exec -it 87b7c0d54971 ls -l /var/opt/gitlab/backups
total 200
-rw------- 1 root root 204800 Jul 26 12:52 1595767959_2020_07_26_13.2.1_gitlab_backup.tar
$ 
$ docker exec -it 87b7c0d54971 date
Sun Jul 26 12:54:05 UTC 2020

6. バックアップファイルの保存先変更

大体、470行目くらいに出てきます。

$ docker exec -it 87b7c0d54971 vi /etc/gitlab/gitlab.rb
gitlab.rb(BEFORE)
### Backup Settings
###! Docs: https://docs.gitlab.com/omnibus/settings/backups.html

# gitlab_rails['manage_backup_path'] = true
# gitlab_rails['backup_path'] = "/var/opt/gitlab/backups"
gitlab.rb(AFTER)
### Backup Settings
###! Docs: https://docs.gitlab.com/omnibus/settings/backups.html

gitlab_rails['manage_backup_path'] = true
gitlab_rails['backup_path'] = "/var/opt/gitlab/backups2020"

7. 設定を反映

これをやっておくことが重要なようです。

$ docker exec -it 87b7c0d54971 gitlab-ctl reconfigure
Starting Chef Infra Client, version 15.9.17
resolving cookbooks for run list: ["gitlab"]
Synchronizing Cookbooks:
  - gitlab (0.0.1)
  - redis (0.1.0)
  - package (0.1.0)
  - registry (0.1.0)
  - postgresql (0.1.0)
  - consul (0.1.0)
  - gitaly (0.1.0)
  - letsencrypt (0.1.0)
  - runit (5.1.3)
  - monitoring (0.1.0)
  - mattermost (0.1.0)
  - crond (0.1.0)
  - nginx (0.1.0)
  - praefect (0.1.0)
  - acme (4.1.1)
Installing Cookbook Gems:

〜省略〜

Recipe: gitlab::puma
  * runit_service[puma] action restart (up to date)
  * runit_service[puma] action restart (up to date)
Recipe: gitlab::sidekiq-cluster
  * sidekiq_service[sidekiq] action restart
  Recipe: <Dynamically Defined Resource>
    * service[sidekiq] action nothing (skipped due to action :nothing)
    * runit_service[sidekiq] action restart (up to date)
     (up to date)
Recipe: gitlab::gitlab-rails
  * execute[clear the gitlab-rails cache] action run
    - execute /opt/gitlab/bin/gitlab-rake cache:clear

Running handlers:
Running handlers complete
Chef Infra Client finished, 9/728 resources updated in 01 minutes 45 seconds
gitlab Reconfigured!

8. アプリケーションデータのバックアップ再取得

もう一度バックアップを取得してみます。

$ docker exec -it 87b7c0d54971 gitlab-rake gitlab:backup:create
2020-07-26 13:16:06 +0000 -- Dumping database ... 
Dumping PostgreSQL database gitlabhq_production ... [DONE]
2020-07-26 13:16:50 +0000 -- done
2020-07-26 13:16:50 +0000 -- Dumping repositories ...
2020-07-26 13:16:51 +0000 -- done
2020-07-26 13:16:51 +0000 -- Dumping uploads ... 
2020-07-26 13:16:51 +0000 -- done
2020-07-26 13:16:51 +0000 -- Dumping builds ... 
2020-07-26 13:16:51 +0000 -- done
2020-07-26 13:16:51 +0000 -- Dumping artifacts ... 
2020-07-26 13:16:51 +0000 -- done
2020-07-26 13:16:51 +0000 -- Dumping pages ... 
2020-07-26 13:16:51 +0000 -- done
2020-07-26 13:16:51 +0000 -- Dumping lfs objects ... 
2020-07-26 13:16:51 +0000 -- done
2020-07-26 13:16:51 +0000 -- Dumping container registry images ... 
2020-07-26 13:16:51 +0000 -- [DISABLED]
Creating backup archive: 1595769411_2020_07_26_13.2.1_gitlab_backup.tar ... done
Uploading backup archive to remote storage  ... skipped
Deleting tmp directories ... done
done
done
done
done
done
done
done
Deleting old backups ... skipping
Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data 
and are not included in this backup. You will need these files to restore a backup.
Please back them up manually.
Backup task is done.

9. バックアップの保存先が変わったことの確認

/var/opt/gitlab/backupsを確認して、先ほど作成したバックアップしか無いこと、新しいバックアップが存在しないことを確認します。

$ docker exec -it 87b7c0d54971 ls -l /var/opt/gitlab/backups
total 200
-rw------- 1 root root 204800 Jul 26 12:52 1595767959_2020_07_26_13.2.1_gitlab_backup.tar

新しく指定したフォルダに格納されていることを確認します。

$ docker exec -it 87b7c0d54971 ls -l /var/opt/gitlab/backups2020
total 200
-rw------- 1 root root 204800 Jul 26 13:16 1595769411_2020_07_26_13.2.1_gitlab_backup.tar

感想

dockerでGitLabを構築するのは、そんなに苦労せずにできました。
やはり慣れると便利・・・。
オーケストレーションを理解していないので、次はKubernatesですかね。

GitLabのバックアップコマンドは、一度動きを見ておきたかったので、docker越しだけど実行できてよかった。
あとは、データ量があるものをバックアップしようとしたときに、どのくらいの時間がかかるのか・・・ですね。
それは会社の仮想サーバ上で試すことにします。

参考にさせていただいた記事など

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Lambda 用の Java11 コードを docker-lambda 環境でローカル開発するメモ

Docker に慣れちゃうと、別にインストールしても問題ないものまでコンテナ上で動かしたくなりません?特に更新が激しいものはアップデートの導入が面倒なので、つい Docker image を探しがち。

というわけで、AWS Lambda で実行する Java 11 コードを、docker-lambda を用いてローカル環境で開発・テスト実行させてみました。Docker 以外はインストール不要なので、気軽に試せて良い感じです。

ググってみても python や nodejs の説明ばかりヒットする気がしたので、簡単なメモとしてまとめておきます。

docker-lambda とは

docker-lambda は AWS Lambda 開発環境を Docker ベースで提供するものです。以下、概要部分を簡単に訳しておきますね。

インストールされているソフトウェアとライブラリ、ファイル構造と権限、環境変数、コンテキストオブジェクトと動作を含む「ライブ AWS Lambda 環境」をほぼ同じように複製するサンドボックス化されたローカル環境。ユーザーと実行中のプロセスも同じです。
image.png
docker-lambda を使用することで、同じ厳密な Lambda 環境で関数を実行し、ライブでデプロイしたときに同じ動作を示せます。AWS Lambda に存在するライブラリバージョンと同様にネイティブ依存関係をコンパイルし、AWS CLI を使用してデプロイすることもできます。

サンプルコードの導入

テスト用のフォルダ(ディレクトリ)を作成し、docker-lambda/examples/java/ にあるファイルを配置します。該当リポジトリ を丸ごと clone もしくは zip 形式でダウンロードして、該当部分だけをコピーすると楽でしょう。

サンプルコードのビルド

ダウンロードしたサンプルは Java のソースコード です。テスト用のフォルダに移動し、Docker コマンドでビルド(コードのコンパイル)を実施します。

docker run --rm -v $PWD:/var/task lambci/lambda:build-java11 gradle build

なお私は Windows 環境なので $PWD が使えないため、実際のフォルダ (今回は c:/work/java/docker-lambda) を指定しました。

docker run --rm -v c:/work/java/docker-lambda:/var/task lambci/lambda:build-java11 gradle build

問題無く実行されれば build フォルダが作成され、その中に幾つかのフォルダが生成されるはずです。この中の docker フォルダに、コンパイルされたクラスのバイトコードと、実行に必要なライブラリが格納されています。
image.png

サンプルコードの実行

作成された実行クラスは、build/docker/ フォルダ内にあります。以下のコマンドで実行してみます。

docker run --rm -v $PWD/build/docker:/var/task \
  lambci/lambda:java11 org.lambci.lambda.ExampleHandler \
  '{"some": "event"}'

Windows 環境では改行を使わず、JSON の指定方法も修正して、実際には以下のように実施しています。

docker run --rm -v c:/work/java/docker-lambda/build/docker:/var/task lambci/lambda:java11 org.lambci.lambda.ExampleHandler "{\"some\": \"event\"}"

AWS SDK API を利用してみる

サンプルの実行だけで終わるのも寂しいですので、S3 のバケット一覧を取得してみます。

サンプルコードの修正

AWSのガイド を参考に、まずは import 文を追加します。

src/main/java/org/lambci/lambda/ExampleHandler.java
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.Bucket;
import java.util.List;

そして handleRequest 関数の終わり (Return文の前) に以下のコードを追加します。

src/main/java/org/lambci/lambda/ExampleHandler.java
        logger.log("Your Amazon S3 buckets are:\n");
        final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
        List<Bucket> buckets = s3.listBuckets();
        for (Bucket b : buckets) {
            logger.log("* " + b.getName() + "\n");
        }

この段階でビルドを実施すると、S3 関連の SDK ライブラリが見つからずエラーになります。テスト用フォルダにある build.gradle にビルド用の設定(2行)を追加します。

build.gradle
dependencies {
    implementation platform('com.amazonaws:aws-java-sdk-bom:1.11.99') // この行を追加
    implementation (
        'com.amazonaws:aws-lambda-java-core:1.2.0',
        'com.amazonaws:aws-lambda-java-events:2.2.7', // カンマ追加
        'com.amazonaws:aws-java-sdk-s3' // この行を追加
    )
}

これで先ほどと同じコマンドで、ビルドできるようになりました。

修正したサンプルコードの実行

さきほどと同様にコードを実行しようとすると、権限エラーになります。以下のように -e オプションで AWS_ACCESS_KEYAWS_SECRET_ACCESS_KEY の値を渡してあげましょう。

docker run --rm -v $PWD/build/docker:/var/task \
  -e AWS_ACCESS_KEY_ID=XXX -e AWS_SECRET_ACCESS_KEY=XXXXXX \
  lambci/lambda:java11 org.lambci.lambda.ExampleHandler \
  '{"some": "event"}'

Windows の場合は1行にまとめて、JSON 表記など修正して以下のように実行します。

docker run --rm -v c:/work/java/docker-lambda/build/docker:/var/task -e AWS_ACCESS_KEY_ID=XXX -e AWS_SECRET_ACCESS_KEY=XXXXXX lambci/lambda:java11 org.lambci.lambda.ExampleHandler "{\"some\": \"event\"}"

こんな感じで s3 バケットのリストが得られれば成功です。
image.png

AWS_ACCESS_KEYAWS_SECRET_ACCESS_KEY は、AWS でユーザーを作成して、その「認証情報」タブから作成・取得ができます。なんの権限もない新規ユーザーを作成し、開発対象である Lambda 関数と同じアクセス権限(ロールやポリシー)を与えて利用するのが良さそうです。

stay-open モードで開発する

4つのオプションを追加して、更に便利に開発していきましょう。

  • 環境変数 DOCKER_LAMBDA_STAY_OPEN=1 で API 待ち受けモードになる
  • -p 9001:9001 オプションで待ち受けするポートを指定する
  • 環境変数 DOCKER_LAMBDA_WATCH=1 でファイルの変更を監視し、サービスの再スタートを実施する
  • --restart on-failure Dockerオプションでエラー時に自動的に再起動する (Java 11では必須ではない)

以下のようなコマンド実行になります。

docker run -v $PWD/build/docker:/var/task \
  --restart on-failure \
  -e DOCKER_LAMBDA_WATCH=1 -e DOCKER_LAMBDA_STAY_OPEN=1 -p 9001:9001 \
  -e AWS_ACCESS_KEY_ID=XXX -e AWS_SECRET_ACCESS_KEY=XXXXXX \
  lambci/lambda:java11 org.lambci.lambda.ExampleHandler \
  '{"some": "event"}'

Windows の場合は以下のように実行します。

docker run -v c:/work/java/docker-lambda/build/docker:/var/task --restart on-failure -e DOCKER_LAMBDA_WATCH=1 -e DOCKER_LAMBDA_STAY_OPEN=1 -p 9001:9001 -e AWS_ACCESS_KEY_ID=XXX -e AWS_SECRET_ACCESS_KEY=XXXXXX lambci/lambda:java11 org.lambci.lambda.ExampleHandler "{\"some\": \"event\"}"

別なターミナル画面を開き、以下のように curl などでアクセスしてみましょう。

curl -d "{}" http://localhost:9001/2015-03-31/functions/myfunction/invocations

以下のように Return 文の内容 "Hello World!" が返ってくれば動作は成功です。ログは Docker を実行したほうのターミナルのほうに表示されています。
image.png

試しにソースコードを修正してビルドを実行すると、/build/docker フォルダの変更を感知して、サービスが自動的に再始動します。

おわりに

Docker 環境されあれば docker-lambda を用いてローカルで AWS Lambda 関数の開発を実施できます。好みのエディタでサクサク開発でき、テストも容易です。いろんなコードを書いて、試してみましょう!

それではまた。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue + Vue Router + Vuex + Laravel のチュートリアル(@MasahiroHarada 様 作成)を進める最中に詰まった部分の原因と対策

はじめに

こちらの記事は、@MasahiroHarada 様が作成された以下の記事をのチュートリアルを、実際に自分が行ってみて、詰まった部分や勘違いしていた部分を、他のチュートリアルに挑戦される方向けに残したものです。

Laravel 6 & PHP 7.4 対応】Vue + Vue Router + Vuex + Laravel チュートリアル(全16回)を書きました。

本当に素晴らしい記事で、Laravel、Vue、spa設計の知見が深まりました。
この場を借りて、改めて感謝申し上げます。

※記事の執筆にあたり、一応ご本人から確認はいただいておりますが、共著でもないため、間違いやご指摘、ご意見は全て私の方に直接いただきますよう、お願い申し上げます。

それでは、よろしくお願いします。

私の開発環境と前提

私が使用した開発環境です。

Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (3) SPA開発環境とVue Routerの記事を参考に、Dockerで作成しました。

Laravelは7.19.0、OSはMacです。

詳しいことは上記の記事にまとめてくださっていますが、前提条件としてご了承ください。
次章より、実際に詰まった部分と解決策を述べます。

npm run watch で何も表示されない

最初に遭遇したエラーは、(3) SPA開発環境とVue Routerのフロントエンドのビルドの項目で、npm run watchを入力しても何も表示されなかったことです。

これは、SPAの仕組み上当然のことで、バックエンドの(Laravelの)サーバーを立てていなかったことが原因でした。

ターミナル等でシェルをもう一つ用意し、バックエンドのサーバーをphp artisan serve --host 0.0.0.0 --port 8081で立ててから、もう一つの方でnpm run watchを行うと無事表示されました。

Illuminate\Foundation\Auth\RegistersUsers.php がない

(4) 認証APIの部分です。
これは、私と同じLaravelの7系、もしくは6系を使っている方は遭遇するかと思います。

対策の詳細はこちらの公式にも載っています。
https://readouble.com/laravel/7.x/ja/authentication.html

具体的には、以下のコードをcomposerファイルのあるディレクトリで実行すると現れてくれるはずです。

# Laravel6系
composer require laravel/ui:^1.0 --dev

# Laravel7系
composer require laravel/ui

参考記事
更新! Laravel6/7「make:Auth」が無くなった 〜Laravel6/7でのLogin機能の実装方法〜MyMemo

なぜか新規登録ができない

これが個人的には一番びっくりなエラーでした。コードはあっていて新規登録をしようとしても、

POST http://localhost:3000/api/register 405 (Method Not Allowed) message: "The POST method is not supported for this route. Supported methods: GET, HEAD."

というエラーが出ます。これの解決策は、なんとパスワードを8文字以上にすることでした。
Railsのdeviseというログイン機能を作ってくれるライブラリをよく使用していて、そちらは6文字だったので油断しておりました。

参考記事
ユーザー認証のパスワード制限の変更

コントローラーで処理がされない

チュートリアルを進めていき、理解している部分は基本的にコピペで行っていたのですが、それ通りに貼り付けているはずなのにコントローラーが反応してくれない場面がありました。

原因はDIのし忘れ(namespaceの書き忘れ)でした。

Laravelでは別ファイルから使いたい要素を持ってくるときに、use App\Http\Requests\StoreComment;と言った形で主にファイル冒頭に記載をするのですが、内容のコードだけを貼って、こちらをコピペすることを忘れていました。

結果、参照ができずにエラーが出たわけです。しっかりと記事を読んで、コピーのし忘れがないか確認しましょう。

Failed to load resource: the server responded with a status of 405 (Method Not Allowed) が出る

これは、ルーティングに誤りがありました。今回のチュートリアルでは、api.phpとweb.php二つのルーティングがあります。apiを叩く処理を間違った方に書いており、このエラーが発生しました。

「ルーティングを書いている場所はあっているか?」チェックをしてみると解決するかもしれません。

エラーメッセージがインポートできない

(8) エラーハンドリングの章で記載ミス?と思われるものがあります。(2020/7/26現在)コメント欄で@MasahiroHarada 様が回答されていますが、一応記事がそのままだったのでこちらにも記載いたしました。

router.js
import SystemError from './pages/errors/System.vue'
// ここのままだとエラーになるので、
// import SystemError from './pages/errors/500.vue'
// としてあげましょう

/* 中略 */

const routes = [
  /* 中略 */
  {
    path: '/500',
    component: SystemError
  }
]

写真投稿APIのテストが通らない

Dockerで作開発をしていると、 (9) 写真投稿APIのテストが通りません、原因は記事のコメント欄にもあったのですが、一応こちらにまとめます。

基本的には紹介されているこちらの記事通りにやっていただきたいのですが、私はDocker初学者だったので「再ビルドしてください」というのが、どうするのかわかりませんでした。

私の場合docker build -t vuesplash_vuesplash_web .で解決しました。(ピリオドも必要です)

謝辞

以上が、自分がチュートリアル実行時に遭遇したエラーです。初歩的なミスもあり、そのような振り返り学習ができたという点でも、こちらのチュートリアルは素晴らしかったです…本当にありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VultrにDocker環境を作成する

はじめに

格安VPCのVultrにDocker環境を作ります。構築中は最安プラン($5/Month)でよいと思います。

Vultrはじめにやること(詳細は省略)

構築中はファイアウォールで自分のみアクセスできるようにし2要素認証を有効にしておくことを推奨します。

  • インスタンス作成
  • ファイアウォールルール作成
  • 2要素認証の有効化

OSバージョンを確認

Ubuntuで環境作りたかったのでOSはUbuntu 20.04を選択しました。最新版のUbuntuが選択できるの嬉しいですね。
数分で環境ができあがりますのでSSHで接続してOSバージョンを確認してみます。

$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

パッケージを最新版にする

とりあえずパッケージを最新にしておきます。

$ sudo apt install aptitude
$ sudo aptitude update
$ sudo aptitude upgrade

SSHのセキュリティ対策

デフォルトだとSSHが22/TCPで接続を受け付けてしまうので待ち受けポート番号を変更します。ついでにrootでログインできないようにもします。(事前にユーザを作成しておいてくださいね)

/etc/ssh/sshd_config
Port 9443
PermitRootLogin no
$ sudo service sshd restart

タイムゾーンを日本に変更

$ timedatectl set-timezone Asia/Tokyo
$ timedatectl
               Local time: Sun 2020-07-26 11:29:38 JST
           Universal time: Sun 2020-07-26 02:29:38 UTC
                 RTC time: Sun 2020-07-26 02:29:39    
                Time zone: Asia/Tokyo (JST, +0900)    
System clock synchronized: yes                        
              NTP service: active                     
          RTC in local TZ: no 

Dockerをインストール

Dockerをインストールします。公式サイトの手順通りです。

$ curl https://get.docker.com | sh
$ sudo usermod -aG docker <username>
$ sudo systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-07-26 11:13:14 JST; 16min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 568 (dockerd)
      Tasks: 27
     Memory: 121.6M
     CGroup: /system.slice/docker.service
             └─568 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

$ ps aux |grep docker
root         568  0.3  9.3 935036 93552 ?        Ssl  11:12   0:03 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

$ docker --version
Docker version 19.03.12, build 48a66213fe

Docker Composeをインストール

Docker Composeをインストールします。公式サイトの手順通りですが最新バージョンのURL(1.26.2の部分)はタイミングによって変わるので確認しておいてください。

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose version 1.26.2, build eefe0d31

スナップショットを取得

最低限の環境ができあがったところでVultrでスナップショットを取得しておきましょう。これをやっておけばいつでもこの環境に戻すことが可能です。
img05.JPG

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker環境にてコマンドラインからgnome-terminal起動時にエラーが出て起動しない

Docker環境にてコマンドラインからgnome-terminal起動時にエラーが出て起動しない

Error constructing proxy for org.gnome.Terminal:/org/gnome/Terminal/Factory0: Error calling StartServiceByName for org.gnome.Terminal: GDBus.Error:org.freedesktop.DBus.Error.Spawn.ChildExited: Process org.gnome.Terminal exited with status 8

Docker環境でのlocaleの設定が足りなかった。
以下の通りDockerfileにlocaleを設定する記述を追加して解決

Dockerfile
RUN locale-gen ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:jp
ENV LC_ALL ja_JP.UTF-8

#参考
Docker: コンテナのlocaleを設定したいhttps://wiki.gnome.org/Apps/Terminal/FAQ
https://askubuntu.com/questions/608330/problem-with-gnome-terminal-on-gnome-3-12-2

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Mac】「Docker」で「Ruby on Rails 6」「React」と「MySQL 8」で環境構築(CRUDのサンプル付)

■ はじめに

SESエンジニアとして、PHPをメインに参画し、現在はJava案件に参画しているTatsuyaです。
そしてこの度転職が決まりまして、9月から新しい職場に!!!!
楽しみもある反面、実は不安要素が。。。

それは、、、
次の職場は!!Ruby on Rails!!やったことない!!

僕「学習しないと転職した瞬間からお荷物確定ダァー」

と焦り散らかし始めて、先日からRuby on Railsの学習に励み始めたわけなのですが。。。

僕「Rubyの公式チュートリアルめちゃくちゃ大変すぎないか!?さらにHerokuとかも使うの!?結構大掛かり!?」

というので、実は挫折しちゃいました。。。
挫折理由としては、チュートリアル自体が骨太ということもありますが、 Dockerを使った環境構築 も重なって折れちゃいました。(最弱)

僕は、直接自分のMacにRuby環境は作りたくなかったんで、なんとしてでもDockerでローカル環境を整えたかったのです。(次の職場でもDocker使うみたいですしお寿司)

ということで、先人の方々が丁寧に書き上げていただいた貴重な文献を元に、実際に動かしながらRubyの動きがわかるような良い感じの環境を作らせていただいて、そこで学習を進めようという方向に舵を切ることになりました。

その過程で、とてもわかりやすく、実際に手を動かしながら理解しやすいと感じた「環境」「サンプルコード」を有り難くミックスさせていただいたので、そちらの結果の方をこの記事でご紹介できればなと思います。

◇ 大変お世話になった貴重な参考文献(無許可です。すいません。)

以下に記載した方々のお力をお借りして、良い感じのサンプルサイトの構築ができました。ありがとうございます。
これから環境構築作業に入っていきますが、丁寧に進めたい!という方はぜひ僕の記事と一緒に偉大なる先人方の記事を見ていただければかなり深まるのではないかと思います。

◉ 環境

Docker + Ruby on Rails + MySQLで開発環境を新規構築する

  • 丁寧な記事で、詳しくソース毎の解説をしてくれています。またDockerのインストールから記載していただいているので、初めてDockerに触るという方にもオススメです。とてもありがたかったです。

◉ サンプルコード

Rails + React + AjaxでCRUDのサンプルプロジェクト

Rails + React + AjaxでCRUDのサンプルプロジェクト(ソース一式)

  • チュートリアル方式で解説を進めてくださっております。大変わかりやすいです。私はまるっとクローンして動かしたのですが、書きながら学びたい方は順に進めていくのも良いと思います。

◉ その他細かい部分でお世話になった記事

Rails on Dockerでcredentialsをeditしたい

◇ 感謝と謝罪

  • ※基本的に参考記事様の情報をコピペで使用しております。私が今回取り組んだのは、 環境とサンプルコードのミックス なので、変にアレンジさせずにほぼ原型のままで使用させていただいております。貴重なお時間を割いて書き上げていただいた記事を丸々コピーするような形になりまして、大変申し訳ないという気持ちと、Rubyの学習コストを下げていただいて誠に有り難うございますという感謝と謝罪を先にさせていただきたいと思います。

■ 実際に環境を構築していきましょう

◇ 前提条件

  • Mac
  • Docker インストール済みであること
    • まだの方はこちらの記事から
  • git インストール済みであること

◇ 最終的なディレクトリ構成

ディレクトリ構成
mpp_react_crud
  /mysql
    /Dockerfile
    /my.cnf
  /rails
    /app
    /bin
    /config
    /db
    /log
    /node_modules
    /public
    /tmp
      .browserslistrc
      .gitignore
      .ruby-version
      .babel.config.js
      .config.ru
      Dockerfile
      Gemfile
      Gemfile.lock
      LICENSE
      package.json
      pastcss.config.js
      Rakefile
      README.md
      yarn.lock
  docker-compose.yml

◇ サンプルプロジェクトをクローン

terminal
# homeへ
$ cd
# mpp_react_crud ディレクトリを作成
$ mkdir mpp_react_crud
# mpp_react_crud ディレクトリに移動
$ cd mpp_react_crud
# サンプルプロジェクトをclone
$ git clone https://github.com/TakeshiOkamoto/mpp_react_crud.git
# mpp_react_crudプロジェクト の名前を railsに変更
$ mv mpp_react_crud rails

◇ docker-compose.yml の作成

terminal
# 『◇ サンプルプロジェクトをクローン』の続きから

# docker-compose.yml を作成する
$ vi docker-compose.yml
# vim画面が開いたら、「iキー」でINSERTモードにし、以下のymlをコピペしてください。
# コピペが完了したタイミングで、「:wq」で保存をして終了してください。
docker-compose.yml
version: "3.7"
services:
  db:
    build: mysql
    image: mpp_react_crud_db
    container_name: mpp_react_crud_db
    ports:
      - 3306:3306
  app:
    build: rails
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    image: mpp_react_crud_app
    container_name: mpp_react_crud_app
    ports:
      - 3000:3000
    volumes:
      - ./rails:/rails
    depends_on:
      - db

◇ MySQL用のDockerfileとmy.cnfを作成

▼ Dockerfile の作成

terminal
# 『◇ docker-compose.yml の作成』の続きから

# mysql ディレクトリを作成
$ mkdir mysql
# mysql ディレクトリに移動
$ cd mysql
# Dockerfile を作成する
$ vi Dockerfile
# vim画面が開いたら、「iキー」でINSERTモードにし、以下のymlをコピペしてください。
# コピペが完了したタイミングで、「:wq」で保存をして終了してください。
Dockerfile
FROM mysql:8.0.18

ENV MYSQL_ROOT_PASSWORD root_pass

COPY ./my.cnf /etc/mysql/conf.d/my.cnf
RUN mkdir /var/log/mysql
RUN chown mysql:mysql /var/log/mysql
RUN mkdir /var/run/mysql
RUN chown mysql:mysql /var/run/mysql

▼ my.cnf の作成

terminal
# my.cnf を作成する
$ vi my.cnf
# vim画面が開いたら、「iキー」でINSERTモードにし、以下のymlをコピペしてください。
# コピペが完了したタイミングで、「:wq」で保存をして終了してください。
my.cnf
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_bin
datadir=/var/lib/mysql
socket=/var/run/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/var/run/mysql/mysqld.pid
port=3306
default_authentication_plugin= mysql_native_password
[client]
default-character-set=utf8mb4
terminal
# 最後に mpp_react_crud ディレクトリに戻る
$ cd ..

◇ Ruby on Rails用のDockerfileとGemfile.lockを作成

▼ Dockerfile の作成

terminal
# 『◇ MySQL用のDockerfileとmy.cnfを作成』の続きから

# rails ディレクトリに移動
$ cd rails
# Dockerfile を作成する
$ vi Dockerfile
# vim画面が開いたら、「iキー」でINSERTモードにし、以下のymlをコピペしてください。
# コピペが完了したタイミングで、「:wq」で保存をして終了してください。
Dockerfile
FROM ruby:2.6.5

ENV LANG C.UTF-8
ENV APP_HOME /rails

RUN apt-get update -qq && apt-get install -y build-essential nodejs

# もしyarnでエラーが発生した場合
RUN apt-get update -qq && apt-get install -y curl && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && apt-get update && apt-get install -y yarn && apt-get install -y vim

RUN rm -rf /var/lib/apt/lists/*

RUN mkdir $APP_HOME
WORKDIR $APP_HOME
COPY ./Gemfile $APP_HOME/Gemfile
COPY ./Gemfile.lock $APP_HOME/Gemfile.lock
RUN bundle install
COPY . $APP_HOME

EXPOSE  3000

▼ Gemfile.lock の作成

terminal
# Gemfile.lock を作成
# 空ファイルで良いので、touch コマンドで作成します。
$ touch Gemfile.lock

◇ Rails用データベース設定ファイル"database.yml"を編集

terminal
# 『◇ Ruby on Rails用のDockerfileとGemfile.lockを作成』の続きから

# database.yml を編集
$ vi config/database.yml
# vim画面が開いたら、「iキー」でINSERTモードにし、以下のymlをコピペしてください。
# コピペが完了したタイミングで、「:wq」で保存をして終了してください。
database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:  root_pass
  host: db

development:
  <<: *default
  database: mpp_react_crud_development

test:
  <<: *default
  database: mpp_react_crud_test

production:
  <<: *default
  database:
  username:
  password:
terminal
# 最後に mpp_react_crud ディレクトリに戻る
$ cd ..

◇ Dockerイメージをビルド

terminal
# 『◇ Rails用データベース設定ファイル"database.yml"を編集』の続きから
# Docker イメージをビルド
$ docker-compose build

◇ docker-composeでアプリを起動〜プロジェクト設定

terminal
# 『◇ Dockerイメージをビルド』の続きから

# サービスの立ち上げ
$ docker-compose up -d  # -d: バックグラウンドで起動
# bundle インストール
$ docker-compose run app bundle install
# 各種パッケージのインストール
$ docker-compose run app yarn install
# マスターキーの生成
# ファイル生成後、credentials.yml.encの編集画面が表示されるので:q!で終了します。
$ docker-compose run -e EDITOR=vim app rails credentials:edit
# フォルダの生成
$ mkdir rails/app/assets/images

◇ データベース準備

terminal
# 『◇ docker-composeでアプリを起動〜プロジェクト設定』の続きから

# データベースの作成
$ docker-compose run app rails db:create
# 各テーブルの作成
$ docker-compose run app rails db:migrate
# 各テーブルの初期データの作成
$ docker-compose run app rails db:seed

◇ 完成!

最後にコンテナを再起動しましょう。

terminal
$ docker-compose restart

再起動終了後に、http://localhost:3000 にアクセスしてみてください!
すると、以下のようなページが開かれます。

スクリーンショット 2020-07-26 16.49.15.png

以上でサンプルサイトの環境構築終了です!

■ 終わりに

初心者の方だけでなく、経験者の方でもあっても、初めて触る技術の学習にはかなり苦戦すると思います。
そのため、先に「どういうサイトがどのように動いているか」ということを知るだけでも学習効率は上がるんじゃないかなーと思い、今回の作業に取り掛かりました。
まだ私も環境構築をしてすぐにこの記事を書いているので、この環境を使った学習は始めていませんが、実際にログを仕込んでみたりしながら体感的に学ぶ方が飲み込みは早いと考えるので、ガンガンこの環境とこのサイトを元に学習に取り組んでいこうと思います。

この記事は解説部分を完全に端折って、ただただ完成させることだけを目標に書き上げました!
そのため、しっかりと解説を確認したい方は、参考文献様の記事をご確認いただいて、照らし合わせながら進めてほしいと思います。

僕「本当に先人の方々はすげえや。」

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.jsとGo言語で簡単なWebアプリを作成する

初投稿です。
過去の経験の復習かねて、書き起こしました。

概要

成果物はこちらになりますので、VueやGoを始めてみたい方への力になれれば幸いです。
https://github.com/aocm/vue-go-spa-sample

方針としては、なるべくローカルを汚さないことを最優先に考えました。
開発者ごとに環境が違うのも大変ですし、他のプロジェクト(自分の個人開発・仕事)で他のバージョンを利用していたら思わぬ影響が出てしまうのも嫌ですので、直接ローカルにインストールするのはなるべく避けたいです。

今回はDockerを使って、コンテナ内部で開発環境を作って作業していきます。
ただ、Gitについてはローカル(ホスト)でしか利用できない環境になってしまったので、そこは課題です。
(最低限、更新差分はコンテナの中でも確認できるようにしたほうが親切でした。)

対象読者

  • Dockerは最低限環境構築できているけど、Webアプリ開発ってどこから手を付ければいいんだ?という人
  • Goの簡単な動くサンプルが見たい人
  • Vueの簡単な動くサンプルが見たい人

※きれいなコードを書くことが目的ではないのでご了承ください

書くこと

  • なるべくローカルを汚さないような開発環境構築の方法
    • ローカルを汚す...ここでは、各プラグインやソフトウェアのインストールしまくる状態を指します
    • プロジェクトによってバージョンが違うなど色々障害があると思うので、それの対策です
  • 簡単なアプリ作成
    • VueのSPAサンプル
    • Go(Echo)のREST APIサーバー
  • (おまけ)クロスコンパイルしてWindows上でやまびこアプリを起動してみる

ここで書かないこと

  • 本番環境のセッティング、CI/CD、テスト
  • 本番環境を意識したリスク管理
  • 言語の基礎説明
  • Git、GitHubの基本的な使い方

※気が向いたら、時間をつくって別の記事に書くかもしれません

必要事項

  • Docker・docker-composeが使えること
  • Gitが使えること
  • VSCodeをインストールしていること

各種バージョン(執筆時点)

  • Windows10 Pro(1909)
    • 2004であればHomeであってもWSL2を使ってできます
  • Docker(19.03.8)
  • Git(2.27.0)
  • VSCode(1.47.2)
  • VSCodeの拡張機能
    • Docker
    • RemoteContainer
    • Go(コンテナ内部で利用)
    • Vuter(コンテナ内部で利用)

実際の作業

こんな感じですすめました。

  1. ゴール設定
  2. Git管理の開始
  3. 環境構築
  4. VueのSPA作成(Vue Cliでプロジェクト立ち上げまで)
  5. GoのやまびこAPIサーバーの作成
  6. SPAとAPIの連携

ゴール設定

Must

  • Git管理できること
  • ブラウザで入力した文字列を戻すだけのやまびこアプリができること

Optional

  • 文字列をDBに登録できること
  • 過去の入力したすべての文字列をブラウザで閲覧できること

(終わらなかったので、後日やります。たぶん。)

Git管理の開始

  • Gitプロジェクトの作成
> mkdir vue-go-spa-sample
> cd vue-go-spa-sample

> git init
Initialized empty Git repository in C:/xxxxxxxxxxxx/repository/aocm/vue-go-spa-sample/.git/

> git commit --allow-empty -m "first commit"
[master (root-commit) 2df398f] first commit

環境構築

  • Vue用、Go用、MySQL用のDockerfileを作成して、docker-compose.ymlで一括管理
    • ファイルの中身については割愛
    • 基本的に枠だけ用意して、あとからポチポチメンテナンスしてこうというスタンスなDockerfileです
    • 理想はcompose upのタイミングでなるべくすませるべきです。(作業者によって開発環境が変わらないようにするために、ある程度自動で準備ができるようにするべき)
> docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                                NAMES
6491b0eb8e96        vue-go-spa-sample_client   "docker-entrypoint.s…"   9 minutes ago       Up 8 minutes        0.0.0.0:8080->8080/tcp               vgs-client
42d9f8f675b9        vue-go-spa-sample_server   "bash"                   27 minutes ago      Up 8 minutes        0.0.0.0:8000->8000/tcp               vgs-server
e8a1de1c140d        vue-go-spa-sample_db       "docker-entrypoint.s…"   27 minutes ago      Up 8 minutes        33060/tcp, 0.0.0.0:33060->3306/tcp   vgs-db

VueのSPA作成

  • RemoteContainerで立ち上げます(必須ではないですが、ローカルを汚さない目的です。)
    ※画像のフォルダマークをクリックすると立ち上がります

image.png

Vue Cliのインストール

/usr/src/app # npm install -g @vue/cli

アプリケーションの作成
※それなりに時間がかかりますので、待っている間Goの方に着手しました。
※カスタマイズについては、好みとか目的によります。今回はRouterだけ使いたいが今後手を加えることを考えていろいろと好みで追加しています。

/usr/src/app # vue create vue-spa
Vue CLI v4.4.6
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, Linter, Unit
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a linter / formatter config: Airbnb
? Pick additional lint features: Lint on save
? Pick a unit testing solution: Jest
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
success Saved lockfile.
Done in 100.17s.
⚓  Running completion hooks...

📄  Generating README.md...

🎉  Successfully created project my-project.
👉  Get started with the following commands:

 $ cd my-project
 $ yarn serve

指示にしたがって起動してみます。

DONE  Compiled successfully in 14361ms 
App running at:
  - Local:   http://localhost:8080/ 

Dockerのポートを解放しておいてあるので、ホストのほうで http://localhost:8080/ をブラウザで開いてみて、画像のように表示されていれば成功です。
image.png

GoでAPI作成

RemoteContainerで立ち上げます。コンテナ内部にVSCodeサーバーを立ち上げてリンクします。
image.png
こちらの画像の出典および詳細: https://code.visualstudio.com/docs/remote/containers

以降は、基本的には各コンテナの中で作業しています

立ち上がり次第、コンテナ内部のVSCodeでGoの拡張機能をインストールします

image.png

インストールしたら、Ctrl + Shift + P で command palette 開いて 「Go: Install/Update tools」 します。
すべてチェックして実行したら、下記のログがでるまで待ちます。
image.png

.
.
Installing github.com/sqs/goreturns SUCCEEDED
Installing golang.org/x/lint/golint SUCCEEDED

All tools successfully installed. You are ready to Go :).

簡単なGoファイルを作って実行します。

package main

import (
    "fmt"
)

func main() {
    fmt.Println("####### start #######")
}
root@42d9f8f675b9:/go/src/github.com/aocm/vue-go-spa-sample# go run main.go 
####### start #######

問題なく動きそうなので、EchoでRestAPIサーバーを立てます。

package main

import (
    "github.com/aocm/vue-go-spa-sample/handler"
    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
)

func main() {
    // Echoのインスタンス作る
    e := echo.New()

    // 全てのリクエストで差し込みたいミドルウェア(ログとか)はここ
    e.Use(middleware.CORS())
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    // ルーティング
    e.POST("/yamabiko", handler.YamabikoAPI())
    e.OPTIONS("/yamabiko", handler.OptionsCheck())

    // サーバー起動
    e.Start(":8000")
}
package handler

import (
    "net/http"

    "github.com/labstack/echo"
)

// YamabikoParam は /yamabiko が受けとるJSONパラメータを定義します。
type YamabikoParam struct {
    Message string `json:"message"`
}

// YamabikoAPI は /api/hello のPost時のJSONデータ生成処理を行います。
func YamabikoAPI() echo.HandlerFunc {
    return func(c echo.Context) error {
        param := new(YamabikoParam)
        if err := c.Bind(param); err != nil {
            return err
        }
        return c.JSON(http.StatusOK, map[string]interface{}{"hello": param.Message})
    }
}

SPAとAPIの連携

VSCodeの拡張機能のVuterをインストールします

登録画面を作成

Yamabiko.vueをつくっていきます。

<template>
  <div>
    <h1>This is an Yamabiko page</h1>
    <input v-model="message" placeholder="Say Yahho">
    <button @click="Send">Send</button>
    <p>Yamabiko : {{ yamabiko }}</p>
  </div>
</template>

<script>
export default {
  name: 'Yamabiko',
  data() {
    return {
      message: '',
      yamabiko: '',
    };
  },
  methods: {
    async Send() {
      const yamabiko = await this.CallYamabikoAPI().then((res) => res.json());
      this.yamabiko = yamabiko.message;
      window.alert(this.yamabiko);
    },

    async CallYamabikoAPI() {
      const url = 'http://localhost:8000/yamabiko';
      const data = {
        message: this.message,
      };
      try {
        return await window.fetch(url, {
          method: 'POST',
          headers: {
            'X-Requested-With': 'csrf', // csrf header
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data),
        });
      } catch (e) {
        console.log(e);
        return e;
      }
    },
  },
};
</script>

image.png

image.png

Mustの「ブラウザで入力した文字列を戻すだけのやまびこアプリができること」が達成できました!

おまけ

Linux向けにビルドして、コンテナ内部で実行してみる

root@f83b97e201a6:/go/src/github.com/aocm/vue-go-spa-sample# GOOS=linux GOARCH=amd64 go build main.go 
root@f83b97e201a6:/go/src/github.com/aocm/vue-go-spa-sample# ./main

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.1.16
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8000

フロントからも利用することができましたのでOKです。

Windows向けにビルドしてホストで実行してみる

portが被ると失敗しますので、番号を8001に変更した後ビルドしてみます

root@f83b97e201a6:/go/src/github.com/aocm/vue-go-spa-sample# GOOS=windows GOARCH=386 go build -o yamabiko.exe main.go

Windowsで実行してみるとこのように窓が立ち上がり、実際に動くことが確認できます。
image.png

(簡単にクロスコンパイルするのほんとすごい。。。)


おわりに

久しぶりにプログラム書いたのでところどころ詰まるところがありました。
この記事とプログラムの考案・コーディングに合計8時間くらいかかってしまったので、学習を習慣づける・コーディング力を高める・利用できるアセットを増やすためにもう少し軽めに、情報量を狭く深くアウトプットしつづけたいなとも思いました。

かなり改善点が多いコードなのでプロダクトに利用できる状態じゃないのも事実であり、アセット化するためにももっと時間をかけたいです。

それにしても、やりたいこと知りたいことに対して時間が圧倒的に足りないですね。
もし読者様の作業時短になれていれば幸いです。もし無駄なお時間になっていたらすみません。

間違っていること、質問、アドバイスおよび応援コメントなどコメントいただけると幸いです。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerド初心者の学習メモ

はじめに

普段は偉い人との調整とパワポ職人をやっているエセエンジニアです。
エンジニアを名乗っていてDockerをまともに使えないなんて死んだ石だと言われたのでがんばります。
備忘録としてのDocker学習メモです。
環境:MacOSX 10.15.5

書いてあること

  • Dockerをインストールする
  • Nginxのコンテナを立ち上げる
  • コンテナシェルに接続する
  • Linkオプションを使ってリバプロサーバ経由のスタティックサーバを表示させる
  • メモ:コンテナ作成から削除までのステータス一覧
  • まとめ

Dockerをインストールする

Dockerでググってインストールする。参考にしている記事とサイトのレイアウトが違っても怯んではいけない。

スクリーンショット 2020-07-26 15.23.28.png

Get Startedを選んで

スクリーンショット 2020-07-26 15.23.51.png

Docker Desktopの欄から選んでダウンロード。あとはダイアログにしたがってインストールする。

余談だが、参考サイトでは誰もDockerのことをDocker Desktopと呼ばないので、このページとは別に「Docker」のインストールサイトがあるのかと思い10分くらい探した。そんなことはなかった。

ついでにDocker Hubのアカウントも作っておく。

スクリーンショット 2020-07-26 15.27.11.png

お手軽。

Nginxのコンテナを立ち上げる(練習)

えぬじんえっくす、と呼ぶらしい。フリーでオープンソースのWebサーバ。Apacheなら知ってるけどこちらはよく知らなかった。

コンテナ立ち上げは、nginxにかかれているコマンドをコピペしてターミナルに打ち込むだけ。

https://hub.docker.com/_/nginx
$docker run --name test-nginx -v /test/content:/usr/share/nginx/html:ro -d nginx

参考文献の記載
$docker run
--name <コンテナ名>
-d
-v <ホスト側のディレクトリ>:<コンテナ側のマウントポイント>:<オプション>
-p <ホスト側のポート番号>:<コンテナ側のポート番号>
<イメージ名>

  • -dオプションはバックグラウンド動作させるオプションらしい。ないとフォアグラウンド挙動になるので、これを実行したターミナルでは別のコマンドを打てなくなる。(デタッチドモード
  • -vオプションは説明がみつからない。もうすこし慣れてから戻ってこよう。
  • -pオプションはまだよくわからない。参考書にはコンテナのポートをホスト側に公開する(?)と書いてあった。
  • -rmオプションはつけておくとゴミが増えない。起動・停止したコンテナを自動的に削除する(デタッチドモード)。通常は起動・停止しているコンテナは残り続け、同じ名前のコンテナは起動できない。

コンテナシェルに接続する

  • $docker attach <コンテナ名>
    • コンテナでシェルを実行している場合のみ。
    • Ctr-p,Ctr-qでコンテナ維持したまま抜けられる
    • exitで抜けた場合コンテナも消える・・
  • $docker exec <コンテナ名> /bin/bash
    • exitで抜けてもコンテナが停止しないので安全
    • 最初うまく挙動しなかった。
      • echo $SHELLの結果、うちは/bin/zshだったので
      • ターミナルの環境設定を/bin/bashに変えたらうまくいった。

ただし、execなどの編集は、$docker historyとかでコミット履歴を見た時に ”/bin/bash"かのコマンド履歴しか残らない。
そのため、操作はDockerfileに書いて履歴を残すことが大事だそうだ。なるほど。

Linkオプションを使ってリバプロサーバ経由のスタティックサーバを表示させる

とてもシンプルに以下の様な構成を作る。

image.png

  • Linkオプション(エイリアスつくれる)が使える。
    • Docker run —link <コンテナ名>:<リンク先コンテナの別名>
    • リバプロサーバのhostsと環境設定に、いい感じの設定を追加してくれる。

ちなみにコンテナ名での名前解決はDockerのネットワークを使うことで作ることができるので、linkじゃなくてもいいらしい。linkは環境変数の設定が必要なときに使ったらいいと思う。

リバースプロキシイメージのビルド

リバースプロキシ用のconfファイルを作成する。

reverse-proxy/reverse-proxy.conf
server {
    listen 8080; #8080で呼ばれたら 
    server_name localhost;

    location / {
        proxy_pass http://ss; #ssに通す
    }
}

confファイルと同じフォルダに、以下の内容でDockerfileを作成する。

reverse-proxy/Dockerfile
FROM nginx:latest
COPY /reverse_proxy.conf /etc/nginx/conf.d/reverse_proxy.conf
RUN apt-get update && apt-get install -y inetutils-ping

で、現在のパスを元に、リバースプロキシイメージをビルドする。

bash
$docker build -t reverse-proxy .

スタティックサイトを起動

bash
$docker run --name static-site -e AUTHOR="Tomomi" -d dockersamples/static-site

呼び出される側なので、リバプロコンテナより先に起動しておかなければいけない。
dockersamplesで提供されているイメージを使う。

リバプロイメージからリバースプロキシコンテナを起動

bash
$docker run --name reverse-proxy -p 8080:8080 --link static-site:ss -d reverse-proxy

このときに、--linkオプションでssという名前を関連づける。

localhost:8080にブラウザからアクセスすると、ちゃんとstatic-siteの内容が出てくる。
単純なHello World!よりも達成感があるね。
スクリーンショット 2020-07-26 16.19.57.png

メモ:コンテナ作成から削除までのステータス一覧

コマンドdocker ps または docker inspect <コンテナ名>で確認できる。

  • Created
    • コンテナが作られた状態。Docker createの直後。
  • Running/Up
    • Docker startさせたやつ。
  • Paused
    • Docker pauseさせたやつ。
    • Docker unpauseで解除できる。
  • Restarting
    • 再起動中のステータス、見られることはあまりない。
  • Exited
    • コンテナ実行して終了した状態。
  • Removing
    • コンテナ削除中のステータス、見られることはあまりない。
    • 削除コマンドはDocker rm (起動中の場合は-fで強制終了)
  • Dead
    • なんかで死んじゃった場合のステータス。
    • rmするしかない。

思ったことメモ

思ってたより断然お手軽。イメージコンテナの概念はまだ時々混乱する。'$docker ps'の読み方を早くマスターしたい。
Dockerはファイルサイズを小さくするためにいろいろ工夫されているなあと思った。
オプション系のリファレンスは早めにいい感じの参考文献を見つけて手元に持っておきたい。ググるのが大変。
次はDocker Machineとネットワークあたりまで行きたい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Scrumblrの付箋の色ランダムを固定化して再構築してみる

はじめに

 当チームでもリモートワークが広がってきており、遠隔でもふりかえりができるツールが欲しいということで、ローカル環境で付箋ボードが利用できるScrumblrがチーム内でホットになっています。
しかし、付箋追加の際、色がランダムになっているのが使いづらく、、Forkしてカスタマイズしてみました。
(本当はTrelloなりJamboardなり使えればいいのですが、プロジェクトの都合上、外部への業務情報の書き込み禁止となっており、、)

動くもの

image.png

動作確認環境 バージョン
Windows10 Home Edition バージョン2004
Docker for Windows 2.3.0.3

※いよいよHomeEditionでもDocker for Windowsが動くようになりました!
tomokei5634さんの記事を参考にサクッと導入ができました。

環境構築

Docker上でCentOS7構築

いつも Tips of Rubbishさんのサイトを参考にしたコンテナイメージをベースにして使いまわしています。
今回追加部分は以下の通り。

# 初期構築Shell起動用サービスを登録
COPY ./docker_data/autorun.service /etc/systemd/system/

RUN systemctl enable autorun.service

サービスについては以下のように、OS起動時に立ち上げるようにしています。

[Unit]
After=network-online.target

[Service]
User=root
ExecStart=/root/docker_data/scrumblrInit

[Install]
WantedBy=multi-user.target

サービス起動方法は3244さんの記事を参考にしました。

Scrumblr構築

今回の環境構築では手順を全てShell化してみました。

#!/bin/sh

# redisのインストール
cd /root
wget http://download.redis.io/releases/redis-5.0.0.tar.gz
tar xzf redis-5.0.0.tar.gz

cd /root/redis-5.0.0
make distclean
make
make install

# radis起動
redis-server &

# nodeインストール
curl -sL https://rpm.nodesource.com/setup_10.x | sudo -E bash -

yum -y install nodejs

# Scrumblr構築
cd /root
git clone https://github.com/aliasaria/scrumblr
cd /root/scrumblr

npm install

# Scrumblr起動
node server.js --port 80

こちらはkazosawaさんの記事を参考にしています。

Scrumblrソースのカスタマイズ

ここからが本題ですが、改修量は最小限です。

まず、画面側。「+」ボタンを生成しているのは以下っぽいです。

index.jade
i#create-card.fa.fa-plus-circle.fa-2x.bottom-icon

っぽいというのも、jadeファイル初めて触りました。。

これを以下のように量産すると、「+」ボタンも増えました。

index.jade
i#create-card.fa.fa-plus-circle.fa-2x.bottom-icon
i#create-card2.fa.fa-plus-circle.fa-2x.bottom-icon
i#create-card3.fa.fa-plus-circle.fa-2x.bottom-icon
i#create-card4.fa.fa-plus-circle.fa-2x.bottom-icon

image.png

引き続きソースの中身を見てみると、「+」ボタン押下時のfunctionがありました。

script.js
$("#create-card")
    .click(function() {
        var rotation = Math.random() * 10 - 5; //add a bit of random rotation (+/- 10deg)
        uniqueID = Math.round(Math.random() * 99999999); //is this big enough to assure uniqueness?
        //alert(uniqueID);
        createCard(
            'card' + uniqueID,
            '',
            58, $('div.board-outline').height(), // hack - not a great way to get the new card coordinates, but most consistant ATM
            rotation,
            randomCardColour());
    });

randomCardColour()というメソッドが呼ばれていて、その中身は以下の通り、

script.js
function randomCardColour() {
    var colours = ['yellow', 'green', 'blue', 'white'];

    var i = Math.floor(Math.random() * colours.length);

    return colours[i];
}

ランダムに色を選んでいます。
ので、「#create-card」を以下の通り書き換えてみました。

script.js
$("#create-card")
    .click(function() {
        var rotation = Math.random() * 10 - 5; //add a bit of random rotation (+/- 10deg)
        uniqueID = Math.round(Math.random() * 99999999); //is this big enough to assure uniqueness?
        //alert(uniqueID);
        createCard(
            'card' + uniqueID,
            '',
            58, $('div.board-outline').height(), // hack - not a great way to get the new card coordinates, but most consistant ATM
            rotation,
            'yellow');
    });

$("#create-card2")
    .click(function() {
        var rotation = Math.random() * 10 - 5; //add a bit of random rotation (+/- 10deg)
        uniqueID = Math.round(Math.random() * 99999999); //is this big enough to assure uniqueness?
        //alert(uniqueID);
        createCard(
            'card' + uniqueID,
            '',
            58, $('div.board-outline').height(), // hack - not a great way to get the new card coordinates, but most consistant ATM
            rotation,
            'green');
    });



単純に引数の色指定を固定化しただけです^^;

これで各「+」ボタン毎に色が固定化された付箋を作ることができるようになりました。
いままでは、ふりかえり前に狙った色が出るまでクリック連打して振り分けるという作業が発生してました(笑)

蛇足

DockerHubに公開されているイメージの構築手順ですが、手順上以下の通りとなっています。

  • Redis構築

    docker run -d --name redis-data -v /redis-data:/data redis redis-server --appendonly yes
    
    docker run -d --name redis-scrumblr --volumes-from redis-data redis
    
  • Scrumblr起動

    docker run -it --rm --name scrumblr --link redis-scrumblr:redis -p 8080:8080 scrumblr
    

Redis構築はこれでいいのですが、scrumblrイメージはscrumblrではなく、timmit/scrumblrとしなければ取れません!!(これで小一時間悩んでました。。)

  • Scrumblr起動(通ったコマンド)

    docker run -it --rm --name scrumblr --link redis-scrumblr:redis -p 8080:8080 timmit/scrumblr
    

さいごに

 もともと、我が家のPCにDocker for Windowsを入れてみたかったついでにScrumblrカスタマイズをやってみました。
どれもサクッと動いてよかったなと。
 これからについては、付箋の色を追加するなり成長させたいなと。(付箋自体は画像イメージなので、センスのない付箋を追加することになりそうです。。)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WSL2,dockerで比較的ハマらないメモ

動機

Windows環境でDockerのCudaコンテナを操作の練習をしたかった。
だけどいろんな所の手順書が古すぎて対応できずにしかもGPUの認識すら出来なかった為メモしておく。
(・・・[[gpus]]ってエラー文もう見飽きた)

動作環境(Insider Preview前)

  • Windows 10 Pro 1903ぐらいだったかな
  • Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz 2.81 GHz
  • NVIDIA GeForce RTX2060
  • Dockerは入っているバージョンは忘れた。

Windows手順

以下の各項目を行う。

「Windows の機能の有効化または無効化」から以下の項目をチェックが入っている事を確認する。

image.png

  • 「Hyper-V」
  • 「Windows Subsystem for Linux」
  • 「仮想マシンプラットフォーム」

「Windows Subsystem for Linux」の有効化

>dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

「仮想マシンプラットフォームのオプションコンポーネント」を有効化

>dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

wslのデフォルトバージョンを変更

なんかメッセージ来るが気にしなくていい。

>wsl --set-default-version 2

windows 10 Insider Previewへアップデート

  1. スタートメニューから「設定」を選択
  2. 「更新とセキュリティ」を選択
  3. 「Windows Insider Program」を選択
  4. 「Devチャネル」を選択 image.png

wslのアップデート

  1. 「Windows Update の設定」から「詳細オプション」を選択。
  2. 「Windowsの更新時にほかのMicrosoft製品の更新プログラムを受け取る」を有効化。
  3. 「Windows Update の設定」から「更新プログラムのチェック」を行いアップデート。
  4. 再起動後、以下のコマンドを実行。 image.png
>wsl --update

WSL用のNvidiaのドライバーをインストール

一応wslをシャットダウンする

>wsl --shutdown

Ubuntuをインストール

  1. マイクロソフト・ストアを開く
  2. 検索からUbuntuを検索
  3. お好みのバージョンをインストールする(今回は20.04にした) image.png

WindowsのDocker設定

WSL2の項目がチェックされていると色々とうまくUbuntu上でうまく動作してくれない為外す。
image.png

Ubuntu手順(WSL2上)

ubuntuの初期起動を済ませる。
(ユーザー名を決めるときにそのままウィンドウを閉じるとルートになるのかな?)

CUDAドライバーをインストール

以下のスクリプトを任意の場所に保存し実行する。

#!/bin/sh

# gccとかのインストール
sudo apt -y install build-essential

# 以下のコードはCUDAの公式インストールを行う
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget http://developer.download.nvidia.com/compute/cuda/11.0.2/local_installers/cuda-repo-ubuntu2004-11-0-local_11.0.2-450.51.05-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu2004-11-0-local_11.0.2-450.51.05-1_amd64.deb
sudo apt-key add /var/cuda-repo-ubuntu2004-11-0-local/7fa2af80.pub
sudo apt-get update -y
sudo apt-get upgrade -y

# ここだけ cuda-toolkit を選択する。
apt-get install -y cuda-toolkit-11-0

# 正直ここはいるのかよくわからない。コマンド成功していないみたいなのでいらないかも。(要検証)
echo "set -x PATH /usr/local/cuda-11.0/bin \$PATH" >> .config/fish/config.fish
echo "set -x LD_LIBRARY_PATH /usr/local/cuda-11.0/lib64 \$LD_LIBRARY_PATH" >> .config/fish/config.fish
source .config/fish/config.fish

CUDAの動作確認

以下のコマンドを入力し問題なく動作すればほぼ完了みたいなもの。(これすら出来なかった;;)

cd /usr/local/cuda/samples/4_Finance/BlackScholes
sudo make
./BlackScholes

dockerのインストール

以下のスクリプトを実行

#!/bin/sh
# ここでdockerをインストールする
curl https://get.docker.com | sh

# マウントのエラーが出た為以下のコードで対応した。
sudo mkdir /sys/fs/cgroup/systemd
sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd

nvidia-container-toolkitのインストール

dockerの--gpusのオプション機能のやつかな?
以下のスクリプトを実行.

#!/bin/sh

sudo apt update
sudo apt upgrade

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo service docker restart

動作確認

以下のコマンドを実行しdockerにnvidiaのコンテナが実行できるかを検証する

>sudo docker run --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark

そうすると以下のような結果が得られる。

NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.

> Windowed mode
> Simulation data stored in video memory
> Single precision floating point simulation
> 1 Devices used for simulation
MapSMtoCores for SM 7.5 is undefined.  Default to use 64 Cores/SM
GPU Device 0: "GeForce RTX 2060" with compute capability 7.5

> Compute 7.5 CUDA device: [GeForce RTX 2060]
30720 bodies, total time for 10 iterations: 51.151 ms
= 184.497 billion interactions per second
= 3689.949 single-precision GFLOP/s at 20 flops per interaction

所感

WSLからGPUを利用したdockerを動かくすために古い記事のせいでかなり手こずってしまったし色々不安定な印象でした。
これかもっと環境構築しやすいようにしてほしいのとUbuntuにCudaドライバーいるなんて知らんかったけどそんな説明あったかな?とりあえずUbuntu上のDockerでGPUを動かくすことができたので良かったが、WindowsのDockerとリンクして動くみたいだけどそこも余裕があったら手を出したいと思っている今日この頃。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker imageの一括削除

docker imageの一括削除

docker images -aq | xargs docker rmi
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker上のDBコンテナからダンプ / リストアする方法

dockerでDBサーバーを2つ建ててレプリケーションの設定をしていました。
で、masterからslaveにDBをダンプして移したかったのですが、調べてもなかなかうまくいかなかったので。

1.ダンプする方法

docker exec <db_container_id> mysqldump -u root -p<password> <dbname> > dump.sql

ダンプって失敗しても特に音沙汰なしと言いますか、エラーがでなくて「できた」と思ったら空っぽだったりします。

less dump.sql

これでそれっぽいデータが入っているか確認したらちょっと安心です。

2.リストアする方法
scpでdump.sqlを一方のサーバーから他方のサーバーに移動させました。
で、他方のサーバーにてリストアをします

docker exec -i <container_id> mysql -u root -p<password> <dbname> < dump.sql

障害対応時にもこういうことをやることって沢山ありそうなのでスムーズにできるようになったら焦らずに済むかなと思います。
DBの復旧ってだいぶやばい事故な気がするのでできればやる機会は訪れないでほしいですが。。。

今度レプリケーションや自動フェイルオーバーについても書きたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker Hub1つのリポジトリで複数のimageを管理

この記事について

個人開発でDocker hubで複数のimageの管理を行おうとしたが、複数のDockerfileの場所を指定する方法がよくわからなかったのでメモ

ディレクトリ構造

.
└── infrastructure
    └── docker
        ├── mysql
        │    └──Dockerfile
        ├── nginx
        │    └──Dockerfile
        └── php
            └──Dockerfile

1.Buildsページを開く

スクリーンショット 2020-07-26 0.47.39.png

2.ビルド構成を設定画面を開く

事前にgit hubとの連携をしておきます。
Buildsページの【Configure Automated Builds】ボタンから設定画面に遷移できます。

3.Dockerfileが設置されているgit hubのリポジトリを設定

git hubの連携をすましているとプルダウンにリポジトリ名が出てきます
スクリーンショット 2020-07-26 0.54.56.png

4.Dockerfileの場所を指定

Dockerfileのパスを指定。
デフォルトでは1つしか表示されていませんが、BUILD RULESの【+】ボタンを押すことで追加できます。
パスの指定にはDockerfileの存在するディレクトリーではなく、Dockerfileのパスを指定します。
:no_good: infrastructure/docker/mysql/
:ok_woman: infrastructure/docker/mysql/Dockerfile

スクリーンショット 2020-07-26 1.07.58.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む