20190330のdockerに関する記事は5件です。

[Docker]AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 192.168.0.2. Set the 'ServerName' directive globally to suppress this message

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 192.168.0.2. Set the 'ServerName' directive globally to suppress this message

Dockerで

docker-compose up --build

ってやると必ず出てくるこの警告(私が)。
解決として、https://askubuntu.com/questions/256013/apache-error-could-not-reliably-determine-the-servers-fully-qualified-domain-n
に書いてあることで解決できました。

しかし、このページが英語であること。DockerでないのでDockerの場合の対策方法を書きます。

と言ってもDockerファイルに以下を追記してもらうのみです!

RUN echo "ServerName localhost" | tee /etc/apache2/conf-available/fqdn.conf
RUN a2enconf fqdn

内容はというと、

teeがファイルの書き込みのようなので、
fqdn.confにServerName localhostを書くということみたいです。
書き込みと言っても、もともとないのでファイル作成、書き込みを行う感じですね。

a2enconfはfqdnのファイルを有効にするというものらしい。

なので上記追加でコンテナの中はこんな感じになってます!!

root@056e18a8a70b:/etc/apache2/conf-available# ls
charset.conf  docker-php.conf  fqdn.conf  localized-error-pages.conf  other-vhosts-access-log.conf  security.conf  serve-cgi-bin.conf
root@056e18a8a70b:/etc/apache2/conf-available# cat fqdn.conf
ServerName localhost
root@056e18a8a70b:/etc/apache2/conf-available# 

上記の内容を簡単に説明

現在いるところ(/etc/apache2/conf-available) で フォルダの中のリスト表示(ls)

fqdn.conf が追加されていることが確認できるとで cat で中身確認

ServerName localhostが記述されている

っと言った感じです。

ちなみにこれ、
https://help.ubuntu.com/community/ApacheMySQLPHP#Troubleshooting_Apache
のトラブルシューティングに書いてあるよと言っていますね!

参考
https://askubuntu.com/questions/256013/apache-error-could-not-reliably-determine-the-servers-fully-qualified-domain-n
https://eng-entrance.com/linux-command-tee
http://www.ei.fukui-nct.ac.jp/~t-saitoh/mt/2015/10/debianapache2.html

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

redisとruby on railsの連携

環境
macOS Mojava 10.14.4
Docker 18.09.2
Rails 5.2.2
ruby 2.6.1p33

Webアプリケーションのセッション管理の方法はいくつかあるのですが、ruby on railsは特に指定しなければローカルのCookieにセッションが保存されます。
この状態でrailsを動作させるとCookieが作成されています。
Safariだと
Safari > 環境設定 > プライバシー > CookieとWebサイトのデータ:
を確認すると127.0.0.1のWebサイトのデータが保存されています。(ローカル開発時)

開発だけであればいいんですが、実際の環境でユーザーCookieでセッション情報を管理するのは問題があるのでredisで管理するようにしました。

redisをインストール

$brew install redis
・・・インストールログ・・・
==> Summary
?  /usr/local/Cellar/redis/5.0.4: 13 files, 3.1MB

なんかログにビールが出ました。多分成功の証です。

$redis-cli
Could not connect to Redis at 127.0.0.1:6379: Connection refused

インストールできていました。
redisサーバーが起動してないので接続できていません。

せっかくなんで学習のため、redisサーバーはDockerコンテナを使ってみようかと思います。
Dockerのインストールはこちらを参考にしました。
https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81

redisのDockerコンテナーの起動
停止したら削除するために--rmをつけます。
-pでコンテナのポートを公開します。(ホストのポート6379をコンテナのポート6379に接続)

$docker container run --name local-redis -d --rm -p 6379:6379 redis
Unable to find image 'redis:latest' locally
latest: Pulling from library/redis
27833a3ba0a5: Pull complete 
cde8019a4b43: Pull complete 
97a473b37fb2: Pull complete 
c6fe0dfbb7e3: Pull complete 
39c8f5ba1240: Pull complete 
cfbdd870cf75: Pull complete 
Digest: sha256:000339fb57e0ddf2d48d72f3341e47a8ca3b1beae9bdcb25a96323095b72a79b
Status: Downloaded newer image for redis:latest
cbc1a37039dab71ce996cecdae2cd7cbdbbb78cd76e281ff5837eac3113dd403

dockerイメージがローカルにない場合はDocker Hubから自動でPullしてくれます。
https://hub.docker.com

redisのコンテナが動作しているかの確認

$docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
cbc1a37039da        redis               "docker-entrypoint.s…"   51 seconds ago      Up 50 seconds       0.0.0.0:6379->6379/tcp   local-redis

--nameで指定した名前がNAMESに出力されています。(コンテナの名称)

接続できることを確認します。

redis-cli
127.0.0.1:6379> 

exitを入力し、終了

redisサーバーが用意できたので、railsのセッションをredisで管理するように変更します。

redisを使うためGemfileにredis-railsを追加します。

Gemfile
gem ‘redis-rails’

インストールを行います。

bundle install

railsのセッションの設定を行います。
config/initializers/session_store.rbにredisにセッション情報を格納することを記載します。
特に何も設定していない場合はsession_store.rbは存在しないので作成します。

session_store.rb
Rails.application.config.session_store :redis_store, {
  servers: [
   {
     host: ENV['REDIS_HOST'] || 'localhost',
     port: ENV['REDIS_PORT'] || 6379,
     db: 0,
     namespace: 'session'
   }
  ],
  expire_after: 10.minutes
}

これでセッション情報はredisに記録されるようになります。
実際にredisコンテナを停止させてからrailsを起動するとredisに接続できないことによるエラーが発生します。
SafariでCookieを確認しても127.0.0.1のWebサイトの情報はなくなります。

ローカル開発でこれをやると、毎回redisコンテナを起動させないとエラーで落ちてしまうのでなにか自動化は別途しようと思います。

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

Windows7環境なのにdocker入れて開発することになった話【③docker開発環境編】

はじめに

2章では、不足していたライブラリやソフトウェアを導入し、実際に動作確認を行いました。3章では、2章で動作確認を行ったモジュール群を、docker環境下でどのように実行させるのかを記述していきます。ついにdockerについて触れます。章の構成としては、以下の構成となります。

  • 開発環境における動作確認

    1. コンテナにマウントするためのpythonファイルをテストする
      • python XXXX.pyにてモジュールを実行する(2章で解説したため割愛)
    2. DockerFile、docker-compose.yml、shellを駆使して「1.」と同様の動きを実現する
  • デプロイ環境における動作確認

    1. 開発環境にて作成したDockerFile、docker-compose.ymlを利用してデプロイする

本章を読んでいただくことで、以下のDockerFileを作ることのメリットが伝わると幸いです。

メリット1

dockerをインストール済みの環境(1章参照)であれば、DockerFileとソースコードを共有することで、環境構築なしで実行することができる。GitHubではソースコードの共有まではできるが、開発環境の共有はできないため、共同開発を行う際は非常に有用なメリット。

メリット2

コンテナを利用可能なサービス(AWSではESC)において、簡単にデプロイできる。(本章では開発環境までしか触れられないので次章以降になります)

メリット3

そのアプリケーションを実行するための環境が、DockerFile内に全て書かれているため、開発環境・本番環境に対してどのようなソフトウェアやライブラリが必要か一目で分かる。

一応デメリットも

  • DockerはLinuxカーネルを利用しているため、Linux環境下を推奨。(Windows10からはDocker ToolboxからWSLを利用することで実行できるが、まだまだ不安定なのが現状
  • 開発者が、開発環境にインストールされるソフトウェア/ライブラリを意識せずに開発を行えてしまうため、開発終盤までいっても環境を把握している人はチームに数人しかいないことになる

ついにdockerに触れられるということで前置きが長くなりましたが、今しばらくの間お付き合いください。

第3章

技術バリバリの人「動作確認お疲れ!DockerFile書けた?」

わたし「書けるわけないじゃないですか。そもそもなんですかdockerって」

技術バリバリの人「1章で教えて上げたじゃん」

技術バリバリの人「あ、あと開発環境はもちろんgit使うし、ビルドの情報とかは全部Dockerファイルに書くね。さらに言えばdocker-compose使っちゃえば複数のサーバーをビルドする情報がチーム全体でで同時に管理できちゃったりするねー」

わたし「そういえば単語は一回聞きましたね。でも何言ってるか分からないです。簡単に教えてください!」

技術ばりばりの人「…分かった、Dockerの中身の話を全部話すと長くなるから、1章の辞書整理を見てね。今からは、実際にdockerを使った際に実感できるメリットについて2つ話すね」

docker

技術ばりばりの人「まずこの図を見てね。これは、今回のアプリケーションのライブラリやソフトウェアを、dockerを利用して管理した場合の概念図だよ。左の青い部分がDockerfileで、今回は2つのDockerfileを作ろう。上の『GetNews_Dockerfile』の部分が、インターネットからデータを取得するモジュールに必要なライブラリ/ソフトウェア郡だね。下の『Post_Dockerfile』部分はまだ実装していないけど、取得したデータを外部に送信する部分だね」

わたし「『GetNews_Dockerfile』に、2章でインストールした、スクレイピングで使用する『beautifulsoup4』、AWSにローカルからアクセスする『boto3』、自然言語処理で利用する『mecab』が書いてますね」

技術ばりばりの人「そうだね。2章で既に君が開発環境にインストールしたライブラリ/ソフトウェアを書いただけだよ。次は真ん中の黄色い部分、docker-compose.ymlについて説明するね」

技術ばりばりの人「docker-composeを使うことで、Dockerfileに定義されたコンテナを共通管理することができるんだ。開発したソフトウェアをコンテナ上のどの領域にマウントして、最初に実行するコマンドは何を実行するか等を定義することができるよ」

わたし「もしdocker-composeが無かったらどうなるんですか?」

技術ばりばりの人「もしdocker-composeを使わなかった場合、ビルド・デプロイ・破棄・スケール・ネットワーク設定などのコマンドを、それぞれのDockerコンテナ/イメージに対して実行する必要があるんだ」

わたし「ビルド・デプロイ・破棄だけでも単純にコンテナの数だけコマンドたたく回数が増えちゃうんですね」

技術ばりばりの人「そうだね。正確にはスケールやネットワーク設定についてはDockerfileでやれちゃう部分もあるんだけど、ソフトウェア/ライブラリ部分はDockerfile、ネットワークやスケールなどのインフラ周りについてはdocker-composeに任せちゃう運用が分かりやすいね」

わたし「開発環境の管理が楽なことがなんとなく分かってきました!」

技術ばりばりの人「じゃぁこれでもDockerfileとdocker-compose.ymlが書けるね!よろしく!」

わたし「はい!」

技術ばりばりの人「あ、そうだ、MeCabのDocker化は1癖も2癖もあるらしいから気をつけてね。まぁ大丈夫だね!それじゃ!」

わたし「え、ちょ」

辞書整理

本文章(第3章)を読む上で頭に入れておいたほうが良い文言をピックアップ。文中分からない文言が出たら見返してください。(不足あれば、コメントいただけたら追記していきます)

忙しい人はここだけ読めばDockerの概念がつかめるので、下記は補足として読んでください。

  • コンテナ

    • ホストOS(Linux限定)のkernel機能を利用することで、仮想サーバのような立ち振る舞いをする
    • プロセス・メモリ・デバイス・ネットワーク等、仮想サーバとして必要な部分についてはコンテナごとに保有する
    • ホストOSから見ると、単に1プロセスが起動しているように見えている
    • kernel部分は複数コンテナで共有しているため、kernelにかかわるような操作はできない(正確にはできるがやらない)
    • kernelを共有しているため、kernel依存のエラーである「オープンしているファイルの最大数を超える」等のエラーが、ゲストOS(コンテナ)・ホストOSをまたいで生じることがある
    • Dockerとコンテナは意味が異なり、「Dockerソフトウェアを用いてコンテナという概念を扱っている」が正しい
    • Dockerにおいては、コンテナがkernelを共有して実行している部分は「Docker daemon」が担っている
    • 参考:コンテナ技術の基礎知識
  • Dockerデーモン

    • Linux kernelをコンテナから実行する、いわばホストOSとゲストOS(コンテナ)の橋渡しの部分
    • ホストOSの環境変数、プロキシ設定、DNS設定などをコンテナでも利用したい場合は、Dockerデーモンのオプションを修正する
    • コンテナから見ると、ある意味kernelのような存在
    • Linuxのコマンド、「systemctl」で操作できる
    • 参考:Dockerデーモンに関するもう少し詳しい説明
  • Dockerイメージ

    • コンテナを実行する時に必要なファイルシステム
    • イメージ・レイヤ(Dockerイメージを構成するファイルシステム)の集まり
    • 難しいので、OSおよび必要なアプリケーションに必要なソフトウェア一式が書き込まれているディスクのようなものだと認識していれば良い
    • 自分で1から作成することも可能であるが、GitHubのような形でイDockerメージを管理しているDockerHubから取得することも可能
    • Dockerイメージを作成することをビルド、Dockerイメージをビルドし、アプリケーションをその環境下で実行させることをデプロイと呼んでいる
    • 参考:Dockerイメージとは?【Docker解説】
  • WSL

    • Windows Sybsystem for Linux
    • Windows環境からLinuxの実行環境を実現するサブシステムのこと
    • Windows10以降しか使えない
    • Windows10以降にDockerがWindows環境でも使えるようになった原因
    • Windows10環境にてDockerを利用するには、DockerToolboxをインストールすることで、同ツールがWSLを利用して、Linuxカーネルを叩いている仕組み
    • とはいえ実際動作確認を行っていく中で、まだ不安定であるという噂や、アップデートで動くようになっているという噂もある
    • 参考:WSL上でDocker Engineが動くようになっていたっぽいという話

1.Dockerの設定

第1章で書いた内容も重複しますが、インストールした後の設定が一番難しく、しくじるともちろん動かないので、再掲します。ちなみに、公式ドキュメントが一番参考になります。参考:Docker-docs-ja

前提条件

第1章のDockerのインストールが完了している

proxyおよびDNS設定

社内等プロキシ環境下で実行している場合、Dockerデーモン実行時にプロキシの設定を渡す必要があるため、Dockerデーモンのオプション設定を変更する。(Ubuntu環境を想定しています。)

  • プロキシおよびDNSサーバの設定
    • $ sudo mkdir -p /etc/systemd/system/docker.service.d/
    • $ sudoedit /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://各プロキシサーバ:8080/" "HTTPS_PROXY=http://各プロキシサーバ:8080/" "NO_PROXY=127.0.0.1,localhost" "DOCKER_NETWORK_OPTIONS=--dns 各DNSサーバ"
ExecStart=
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS

Dockerデーモンのオプションファイル自体は別にありますが、『docker.service.d/』以下に記載した設定が、Dockerデーモン実行時に上書かれて実行されます。「ExecStart=」の部分はおまじない。最初に空実行を設定することで、2回目の実行時にオプションを指定した状態で上書き実行ができる仕組み。

  • Dockerデーモンのリロード
    • sudo systemctl daemon-reload
  • Dockerの再起動
    • sudo systemctl restart docker

2.Dockerfileの記載

2章で開発したモジュール郡を動かすためには、下記を「Getnews_Dockerfile(拡張子不要)」という名称で作成する。

Get_news_Dockerfile

FROM python:3.6.5

RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y sudo
RUN pip install --upgrade pip

# ----------- install scrayping module at Python ---------------
RUN pip install beautifulsoup4==4.6.3

# --------------------- mecab configure ------------------------
RUN apt-get install mecab mecab-ipadic libmecab-dev -y
RUN pip install mecab-python3==0.7
RUN git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git /usr/src/mecab-ipadic-neologd \
  && /usr/src/mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -y -p /var/lib/mecab/dic/mecab-ipadic-neologd \
  && rm -rf /usr/src/mecab-ipadic-neologd

# -------------- install aws module at Python ------------------
RUN pip install boto3==1.7.4

WORKDIR ./

解説

  • FROM python:3.6.5
    • DockerHub上から、どのDockerイメージをベースにカスタマイズするかを指定。今回の場合は、Python3.6.5を導入したDockerイメージをベースにカスタマイズを加えている
  • RUN apt-get update && apt-get upgrade -y ~ RUN pip install --upgrade pip
    • apt-getやpipなどソフトウェア管理ツールを最新化しておくおまじない
  • # ----------- install scrayping module at Python ---------------以降
    • スクレイピングに利用するライブラリのインストール
  • # --------------------- mecab configure ------------------------以降
    • MeCabを利用する際に必要なライブラリ/ソフトウェア郡のインストール
  • # -------------- install aws module at Python ------------------以降
    • PythonからAWSアクセスに必要なライブラリのインストール
  • WORKDIR ./
    • デプロイ時、コンテナ内の最初に居るディレクトリを指定

3.docker-compose.ymlの記載

「2.Dockerfile」の記載にて定義したイメージを、コンテナ化して実行するための「docker-compose.yml」を記載する。

docker-compose.yml

version: '2'

services:
    get-news:
      env_file: .env
      build:
        context: ./
        dockerfile: Get_news_Dockerfile
      volumes:
        - ./shell:/root/shell
        - ${get_news_root_dir}/backEndLogic:/root/backEndLogic
        - ${host_aws_credential}:/root/.aws
      command: >
        bash -c "chmod +x /root/shell/get_news.sh && /root/shell/get_news.sh"
      tty: true

解説

  • version: '2'
    • docker-composeのバージョンを指定する。HTMLの一番初めに書くバージョン宣言と同じ(HTML5からは書かないが…)
  • get-news:
    • 任意のコンテナ名称。コンテナを立ち上げる際、ターミナルから指定する名称となる
  • env_file .env
    • AWSのシークレットキーやマウントのパスなど、ホストOSの環境依存でパスを指定する部分については別途「.env」ファイルを作っている。Dockerの設定を完璧に行っても、唯一各環境で書き換える必要がある部分。docker-compose.ymlと同フォルダに作成している
  • build:
    • どのDockerfileをbuildするかをここに書く
    • contextにDockerfileのあるフォルダを指定。今回の場合はdocker-compose.ymlと同フォルダに作成している
    • dockerfileに、このコンテナ(今回の場合get-news)をbuildするために利用するDockerfile物理名称を指定
  • volumes:
    • 各種ローカルからコンテナへのマウント情報。今回の場合は、①shell(後述)、②作成したモジュール郡、③AWSクレデンシャルをマウントする
    • ①shellについては各開発者環境で共通して利用するため、docker-compose.ymlと同フォルダに作成し、envを介さずに相対パスを記載
    • ②作成したモジュール郡および③AWSクレデンシャルについては各開発者環境で異なるため、envで指定した環境変数を記載
  • command: >
    • デプロイ後最初に実行するコマンドを記載。今回はshell(後述)を呼び出すことで、2章で作成したPythonモジュールの管理や、MeCabの辞書コンパイルなどを行う

参考(.envファイル中身)

# ------------------以下ホストの環境に合わせて変更してください ------------------

# ソースディレクトリへのPath. 各コンテナは以下Pathを参照して環境を構築します.
# 指定したディレクトリは、コンテナ上からmountされ参照されます.
get_news_root_dir=/home/username/backEndLogic

# AWSのcredential情報を記載したファイルパス
host_aws_credential=/home/username/.aws

インフラ周りの設定情報についても、docker-compose.ymlに書く。たとえばファイルオープン数が最大に達してしまい、コンテナにもっとリソースを割きたい場合は、volumeと同じ階層に以下のように追記すると良い。

      ulimits:
        nproc: 65535
        nofile:
          soft: 20000
          hard: 40000

※この場合、後述するshellの中にスタックサイズの開放コマンド$ ulimit -s unlimitedを書く必要がある。

4.shellの記載

1~3までで、コンテナ環境の構築や、コンテナ環境へのPythonモジュールのマウントは完了した。しかし、デプロイ後に実際にPythonモジュールを実行したり、MeCabの設定が必要だったりするので、shellを外だしで作成する。

get_news.sh

  • MeCabの辞書がローカルで更新されていた場合、Dockerコンテナ上で毎回ユーザ辞書を更新する必要があるため、shellに任せました
  • 作成したPythonモジュールを実行するために、main.pyに飛ばしました(ここは各々好きに作ればよいと思います)
get_news.sh
# ユーザ辞書のコンパイル
cd /root/backEndLogic/mecabDict

/usr/lib/mecab/mecab-dict-index \
  -d /var/lib/mecab/dic/mecab-ipadic-neologd \
  -u /root/backEndLogic/mecabDict/select_dic.dic \
  -f utf-8 \
  -t utf-8 select_dic.csv

# mecabの設定ファイルにユーザ辞書を追記
cd /etc
sed -i -e 's@.*userdic.*@userdic = /root/backEndLogic/mecabDict/select_dic.dic@' mecabrc

# モジュールのおいてあるパスへ移動
cd /root/backEndLogic/

# News収集機能を実行
python /root/backEndLogic/main.py

main.py

main.py
import subprocess

def main():

    subprocess.check_call(['python','ニュース取得機能.py'])
    print("complete get_news")

    subprocess.check_call(['python','ニュース選定機能.py'])
    print("complete select_target")

if __name__ == '__main__':
    main()

※実際のアプリケーションとは異なるため、簡易的に「ニュース取得機能.py」、「ニュース選定機能.py」を呼び出すような記載としています

docker-compose実行

ここまでくれば、後は2つコマンドを実行してあげるだけです。その前に、現状のフォルダ構成はこうなっています。

.../
    - shell
        - get_news.sh
    - Get_news_Dockerfile
    - docker-compose.yml
    - .env

docker-compose.ymlと同フォルダに、Dockerfileや.env、shellが置いてあります。(docker-compose.ymlの記載次第)

いよいよコマンドを実行します。実行するコマンドはたったの2つ。(コンテナが増えても同様に2つです)

build

プロキシ環境下
- $ docker-compose build --build-arg https_proxy=${https_proxy} --build-arg http_proxy=${http_proxy} get-news
非プロキシ環境下
- $ docker-compose build get-news

コンテナ起動&デプロイ

  • $ docker-compose up

あとがき

わたし「Docker環境で、pythonモジュールが動きました!」

技術バリバリの人「これで実際にAWS環境にデプロイするときも簡単にできるし、モジュールが複雑化しても実行環境を修正するのが簡単になったね!」

技術バリバリの人「次回はついに、取得したデータをフロントエンドに出力する部分を作っていこう!」

続く

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

KubernetesとNode.jsでマイクロサービスを作成する 5/8 Dockerを使ったサービス構築

第5章 Dockerを使ったサービス構築

第4章までで、Twitterライクなマイクロサービスを構成する、3つのサービスを作成してきました。
次はいよいよ、これらのサービスをマイクロサービスとして構築するのですが、いきなりKubernetesを利用する前にワンクッションはさみます。

本章では、各サービスのDockerイメージを作成し、以下のような構成で、ローカルのDocker環境でTwitterライクなサービスを起動します。

microservice-sample-docker.png

完成版のリポジトリはこちらにあるので、実装がうまくいかない場合は比較してみてください。
reireias/microservice-sample-integration

チュートリアル全体

構成

microservice-tutorial01.png

dockerとdocker-compose

まずはローカルにdockerdocker-composeがインストールされていることを確認しましょう。

docker version
Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.4
 Git commit:        e68fc7a
 Built:             Fri Jan 25 14:33:54 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.4
  Git commit:       e68fc7a
  Built:            Thu Jan 24 10:56:33 2019
  OS/Arch:          linux/amd64
  Experimental:     false
docker-compose version
docker-compose version 1.23.2, build 1110ad0
docker-py version: 3.7.0
CPython version: 3.7.2
OpenSSL version: OpenSSL 1.0.2g  1 Mar 2016

microservice-sample-integrationリポジトリの作成

ここからは、各サービスのリポジトリ内のコードを利用して、DockerイメージやKubernetesの設定を作成していくことになります。
そのためには、各サービスのコードが参照できる構成が望ましいです。

今回は下記のディレクトリ構成をとるような、microservice-sample-integrationリポジトリを作成します。

microservice-sample-integration
└── services
    ├── microservice-sample-tweet
    ├── microservice-sample-user
    └── microservice-sample-web

実際の開発現場では、このリポジトリの管理をSREチームが主導して行ったり、各サービスの開発者が協力して行ったりします。

microservice-sample-integrationという名前でリポジトリを作成し、cloneしておきましょう。

つづいて、このリポジトリ内で行う各種操作をMakefileに記述し、makeコマンドから実行できるようにします。
作成するコマンドは下記の通りです。

  • clone: 各サービスをservicesディレクトリ以下にcloneする
  • pull: 各サービスをgit pullする
  • build: 各サービスのDockerイメージのビルドを行う
  • up: 全サービスをdocker-composeを使って、ローカルのDocker環境で立ち上げる
  • down: 全サービスをdocker-composeを使って削除する
  • seed: UserサービスとTweetサービスでscripts/initialize.jsを実行する

Makefileは以下のようになります。

Makefile
WEB_REPOSITORY := https://github.com/reireias/microservice-sample-web
USER_REPOSITORY := https://github.com/reireias/microservice-sample-user
TWEET_RESPOSITORY := https://github.com/reireias/microservice-sample-tweet

clone:
    git clone $(WEB_REPOSITORY) ./services/microservice-sample-web
    git clone $(USER_REPOSITORY) ./services/microservice-sample-user
    git clone $(TWEET_RESPOSITORY) ./services/microservice-sample-tweet

pull:
    cd ./services/microservice-sample-web && git pull
    cd ./services/microservice-sample-user && git pull
    cd ./services/microservice-sample-tweet && git pull

build:
    docker-compose build

up:
    docker-compose up -d

down:
    docker-compose down

seed:
    docker-compose exec user node /app/scripts/initialize.js
    docker-compose exec tweet node /app/scripts/initialize.js

Makefileが作成できたら、make pullを実行し、各サービスをservicesディレクトリ配下へcloneします。

make clone

Dockerイメージの作成

つづいて、各サービスのDockerイメージを作成するための、Dockerファイルを実装していきます。

このファイルから生成されるDockerイメージは本番環境でも使用されます。
実際の開発現場では各サービスが責任を持って作成する場合もありますし、SREチームなど、Dockerのノウハウに長けたチームがサービス横断で管理するケースもあるでしょう。

services/microservice-sample-tweet/Dockerfile
FROM node:11.10-alpine

ENV NODE_ENV=production

WORKDIR /app
RUN apk add --no-cache curl && \
    curl -sfL https://install.goreleaser.com/github.com/tj/node-prune.sh | sh
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait
RUN chmod +x /wait

COPY package.json .
RUN yarn install && ./bin/node-prune
COPY . .
EXPOSE 3000
CMD /wait && yarn start
services/microservice-sample-user/Dockerfile
FROM node:11.10-alpine

ENV NODE_ENV=production

WORKDIR /app
RUN apk add --no-cache curl && \
    curl -sfL https://install.goreleaser.com/github.com/tj/node-prune.sh | sh
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait
RUN chmod +x /wait

COPY package.json .
RUN yarn install && ./bin/node-prune
COPY . .
EXPOSE 3000
CMD /wait && yarn start
services/microservice-sample-web/Dockerfile
FROM node:11.10-alpine as builder

ENV NODE_ENV=production
ARG GITHUB_CLIENT_ID
ARG GITHUB_CLIENT_SECRET
WORKDIR /app

RUN apk add --no-cache curl && \
    curl -sfL https://install.goreleaser.com/github.com/tj/node-prune.sh | sh

COPY package.json .
COPY yarn.lock .
RUN yarn install && ./bin/node-prune
COPY . .
RUN yarn build

FROM node:11.10-alpine

WORKDIR /app
ADD package.json ./
ADD nuxt.config.js ./

COPY --from=builder ./app/server ./server
COPY --from=builder ./app/node_modules ./node_modules
COPY --from=builder ./app/.nuxt ./.nuxt

EXPOSE 3000
CMD yarn start

Webサービスに関してはマルチステージビルドを利用して最終的なイメージのサイズを軽くするように工夫しています。

実装後、各Dockerfilecommitしておきましょう。

docker-compose.ymlの作成

上記で用意したDockerfileを、dockerコマンドを利用してビルド、コンテナの起動等やってもよいのですが、環境変数等、引数が多くなってしまうため、今回はdocker-composeを利用して一元管理します。

docker-compose.ymlに起動したいコンテナの設定を書いていくことで、一括で立ち上げたり、削除することが可能です。

今回は、Webサービス、Userサービス、Tweetサービスと、Userサービス用DB、Tweetサービス用DBの合計5つのコンテナを定義します。

docker-compose.yml
---
version: '3'
services:
  web:
    build:
      context: ./services/microservice-sample-web
      dockerfile: Dockerfile
    image: microservice_web:1.0
    ports:
      - 3000:3000
    environment:
      NUXT_HOST: 0.0.0.0
      USER_SERVICE: http://user:3000
      TWEET_SERVICE: http://tweet:3000
      GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID}
      GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET}
  user:
    build:
      context: ./services/microservice-sample-user
      dockerfile: Dockerfile
    image: microservice_user:1.0
    environment:
      MONGODB_URL: mongodb://user-db:27017/user
      MONGODB_ADMIN_NAME: root
      MONGODB_ADMIN_PASS: example
      WAIT_HOSTS: user-db:27017
    depends_on:
      - user-db
  user-db:
    image: mongo
    volumes:
      - user-db:/data/db
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
  tweet:
    build:
      context: ./services/microservice-sample-tweet
      dockerfile: Dockerfile
    image: microservice_tweet:1.0
    environment:
      MONGODB_URL: mongodb://tweet-db:27017/user
      MONGODB_ADMIN_NAME: root
      MONGODB_ADMIN_PASS: example
      WAIT_HOSTS: tweet-db:27017
      USER_SERVICE: http://user:3000
    depends_on:
      - tweet-db
  tweet-db:
    image: mongo
    volumes:
      - tweet-db:/data/db
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
volumes:
  user-db:
  tweet-db:

GitHubのOAuthのキー等はGit管理する対象ではないので、.envファイルに記述します。
docker-composeの機能により、カレントディレクトリの.envファイルが読み込まれ、docker-compose.yml中で利用することができるようになります。
値はDocker環境の場合エンドポイントがlocalhost:3000と、前章までと同じなため、前章で使用していたのと同じGitHubのOAuth設定が利用可能です。

.env
GITHUB_CLIENT_ID=xxxxxxxxxxxxxxxxxxx
GITHUB_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

services/.gitkeepファイルを作成しておきます。

touch services/.gitkeep

.gitignoreファイルを以下のように設定します。

.gitignore
services/*
!services/.gitkeep
.env

サービスを起動してみる

それでは、サービスを起動してみます。

# Dockerイメージをビルド
make build
# サービスの立ち上げ
make up
# ダミーデータの投入
make seed

http://localhost:3000へアクセスしてみましょう。
問題なく動作していれば本章の実装は完了になります。

第5章まとめ

本章では、各サービスのDockerfileを作成し、docker-composeを利用してマイクロサービスをローカルのDocker環境上に構築しました。

次の章ではいよいよKubernetes上でマイクロサービスを動作させてみます。

次章: 第6章 Kubernetes with minikube

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

metabaseを別サーバーに移行する

はじめに

先日、metabase(構築したのは自分ではない)を別サーバーに移行することがありました。

既存環境にて登録済みのユーザーやクエリを別サーバーに移行する点で、
いまいちそれっぽい情報が見つからず、手間取ったので手順を書いておきます。

やりたいこと

  • metabaseを別サーバーに移行する
  • 移行対象はmetabaseに登録してあるユーザー情報とクエリなど諸々の設定

前提など

公式のdocker imageを使用して、既存環境が構築されている
(それ以外の環境の場合は、やることとしては大体一緒かもしれませんが調べてないので不明です)

公式が書いた下記の記事を参考にして進めています。
metabase: "Running Metabase on Docker" > Mounting a mapped file storage volumeの箇所

ざっくり手順

  1. 設定ファイルが格納されているディレクトリをコンテナから引っこ抜く(デフォルトは/metabase.db
  2. 移行先のサーバーに1.で抜いた設定ファイルが格納されているディレクトリを置き、 docker run -vなどでマウントしてmetabaseを起動する
  3. 起動後は必要に応じて、参照するDBの向き先を変更する

手順

1. 設定ファイルが格納されているディレクトリを引っこ抜く

まずマウントされているか確認

// マウントされていたらホスト側に設定ファイルが入ったディレクトリがあるはずなので、そのディレクトリを移行先に持っていく。
// 仮に、記事通りのコマンドで、マウントして起動されていた場合、`docker inspect ~~~` を叩くと下記の通りになる
$ docker run -d -p 3000:3000 -v ~/metabase-data:/metabase-data -e "MB_DB_FILE=/metabase-data/metabase.db" --name metabase metabase/metabase
$ docker inspect metabaseのコンテナID |grep -E "Source|Destination"
                "Source": "/metabase-data", // ホスト側
                "Destination": "/metabase-data", // コンテナ側

マウントしていない場合、デフォルトではルート直下にmetabase.dbというディレクトリがあるので、このディレクトリをホスト側にコピーする

マウントせずにコンテナを立ち上げてみた場合こうなります
$ docker run -d -p 3000:3000 --name metabase metabase/metabase
// ルートにmetabase.dbというディレクトリが確認できる
$ docker container exec -ti metabase ls /metabase.db
metabase.db.mv.db     metabase.db.trace.db
ホスト側にコピーするコマンドはこれ(一応)
$ docker cp metabase:/metabase.db .
$ tree
.
└── metabase.db
    ├── metabase.db.mv.db
    └── metabase.db.trace.db

2. 移行先でmetabaseを起動する

あとは移行先の任意のディレクトリにmetabase.dbを配置して、下記のコマンドが動くようマウントしてコンテナを立ち上げる

$ docker run -d -p 3000:3000 -v ~/metabase-data:/metabase-data -e "MB_DB_FILE=/metabase-data/metabase.db" --name metabase metabase/metabase

記事のコマンド通りにするなら、
あらかじめ下記のように、~/metabase-dataの下にmetabase.dbを置くディレクトリ構成にし、metabase-detaをマウントする

$ tree -a ~/metabase-data
metabase-data
└── metabase.db
    ├── metabase.db.mv.db
    └── metabase.db.trace.db

3. 起動後

  • 移行前のmetabaseから参照先のDBが変わっていないのであれば、動作確認して終わり
  • ステージングから本番へ、ユーザーやクエリだけ移動するようなケースであれば向き先のDBを変更して終わり
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む