20200922のdockerに関する記事は17件です。

日本語対応版SDAPSのDockerイメージを作ってみた

はじめに

SDAPSで日本語を含む質問票を作成し、レポートを出力することができるように、sdapsコマンドを実行するDockerイメージを作成してみました。

Dockerfileや変更部分は全て下記のGitHubに公開しています。

成果物

GitHubとDockerHubにそれぞれDockerfileとすぐに使えるようイメージを登録し、公開しています。

参考資料

この記事を書く際に参考にしたURLをリストにしています。

開発環境

開発には次のような環境を利用しています。
作成したDockerコンテナも、この開発環境に合わせてUbuntu 20.04をベースにしています。

  • ホストOS
    • Ubuntu 20.04.1 on VMware Workstation 16 Pro
  • Docker
    • 19.03.12 (docker-ce 5:19.03.12~3-0~ubuntu-bionic DEB package)
  • SDAPS
    • 1.9.7 (sdaps 1.9.7-0.2ubuntu2 DEB package)

テスト環境

以下のOS上でDockerイメージが正常に稼動することをテストしています。

  • Linux Distribution
    • Ubuntu 20.04.1 amd64版
  • Windows10 (2004)
    • WSL2 + Docker Desktop for Windows (19.03.12)
  • macOS (10.15.6)
    • Docker Desktop for Mac (19.03.12)

質問票の印刷、読み取りには以下のような機材を使用しています。

  • レーザープリンター (OKI B841)
    • 一般的なPPC用紙 (白色普通紙)
    • 印刷品位 - 高精細 (1200x1200)
  • ドキュメントスキャナ (Brother ADS-3600W)
    • 設定 - TIFFマルチページ・300dpi・モノクロ・長辺とじ

コピー(複写)機の利用について

いまのところ質問票を準備するために、コピー機は使用していません。
過去には問題が発生した経験はありますが、近年はコピー機で臨時に枚数を増やした際にも問題なく処理できています。コピー機を利用する際には、事前に十分テストを重ねてパラメータを保存するなど再現性を確保するようにするのがお勧めです。

使い方

いくつかsdaps由来のバグがあってエラーメッセージが出る場合がありますが、それらを含めてコマンドの利用方法を紹介することにします。

コマンド実行時には、Dockerのvolume機能を利用して、回答票のTeXファイルとプロジェクト・ディレクトリを配置する作業用ディレクトリを作成し、必ずコンテナ内の/projにマウントするようにしてください。

  • Dockerコンテン内の作業用ディレクトリ: /proj

作業の流れ

おおまかには次のような順序で利用しています。

  1. 作業用ディレクトリを作成し、移動 (e.g. dev.proj1/ ; cd dev.proj1)
  2. 質問票のTeXファイルを作成 (e.g. example-ja.tex)
  3. setupコマンドを実行し、プロジェクト・ディレクトリを作成
  4. 記入済みの質問票をスキャンし、TIFFファイルを作業用ディレクトリに配置 (e.g. 01.tif, 02.tif,...)
  5. addコマンドを繰り返し実行し、TIFFファイルを登録
  6. recognizeコマンドを実行し、データを抽出
  7. report_texコマンドでreportファイルを作成 (e.g. report_1.pdf)
  8. csvコマンドで生データを抽出 (e.g. data_1.csv)

準備作業

使用するDockerイメージはコマンド実行前にpullしておきます。

pullの実行例
$ sudo docker pull yasuhiroabe/sdaps-ja:ub2004-2
ub2004-2: Pulling from yasuhiroabe/sdaps-ja
e6ca3592b144: Pull complete
...
Digest: sha256:26458bd39267149a3ccebc36f60a3082e0f519545596166accede1eac4eed8f7
Status: Downloaded newer image for yasuhiroabe/sdaps-ja:ub2004-2
docker.io/yasuhiroabe/sdaps-ja:ub2004-2

作業用ディレクトリについて

GitHubに登録していませんが、作業用にdev.proj1/, dev.proj2/ 作業用ディレクトリを作成し、サンプルの回答票TeXファイル、プロジェクトディレクトリを配置しています。

参考までに最終的なdev.proj2ディレクトリの様子を掲載しておきます。

treeコマンドの出力結果
$ tree dev.proj2
dev.proj2
├── 01.tif
├── 02.tif
├── 20200310_survey
│   ├── 1.tif
│   ├── 2.tif
│   ├── data_1.csv
│   ├── data_2.csv
...
│   ├── questionnaire.pdf
...
│   ├── report_1.pdf
│   ├── report_2.pdf
...
│   ├── translator-sdaps-dictionary-English.dict
...
└── 20200310_survey.tex

1 directory, 43 files

日本語質問票のサンプル

テストのために使用したファイルを掲載しています。
コメントやコンテンツの一部を削除していますので、オリジナルを参照してください。

example.texを元に日本語を埋め込んだ例
\documentclass[
  english,
  a4paper, 
  checkmode=check,
  pagemark,
  stamp]{sdapsclassic}
\usepackage[utf8]{inputenc}
% For demonstration purposes
\usepackage{multicol}

\usepackage{xltxtra}
\setmainfont{IPAPMincho}
\setsansfont{IPAPGothic}
\setmonofont{IPAGothic}
\XeTeXlinebreaklocale "ja"

\author{作者}
\title{タイトル}

\begin{document}
  \begin{questionnaire}
    \begin{info}
      \texttt{info}環境を利用することで、任意のテキストを追加することができます。
    \end{info}

    \addinfo{Date}{10.03.2013}

    \section{5段階評価}
    \singlemark{どのくらいの頻度でSDAPSを利用していますか?}{ほとんどない}{毎日}

  \end{questionnaire}
\end{document}

あらかじめ定義されている定型文の一部についても置換が可能です。

translator-sdaps-dictionary-English.dictの例
\ProvidesDictionary{translator-sdaps-dictionary}{English}

\providetranslation{infotext}{記入方法/Instructions to fill out the form.}
\providetranslation{standard-deviation}{Standard-Deviation}
\providetranslation{info-cross}{マーク例/Check}
\providetranslation{info-correct}{修正例/Uncheck to correct}
\providetranslation{answers}{Answers}
\providetranslation{questionnaireid}{Questionnaire-ID:}
\providetranslation{surveyid}{Survey-ID:}
\providetranslation{draft}{draft}
\providetranslation{info-mark}{For questions with a range (1-5) choose the answer the mark that fits best.}
\providetranslation{info-select}{満足度などについては、5段階で 1つにマークしてください。}
\providetranslation{mean}{Mean}

example-ja.texとtranslator-sdaps-dictionary-English.dictを、作業用ディレクトリ(dev.proj1)に配置した様子は次のようになります。

$ tree dev.proj1/
dev.proj1/
├── example-ja.tex
└── translator-sdaps-dictionary-English.dict

0 directories, 2 files

次のような手順で質問票を生成します。

$ sudo docker run --rm -v `pwd`/dev.proj1:/proj \
  --name sdaps-ja \
  yasuhiroabe/sdaps-ja:ub2004-2 \
  setup --add translator-sdaps-dictionary-English.dict \
  work/ example-ja.tex

質問票は、この例の場合、dev.proj1/work/questionnaire.pdf に配置されます。

image.png

【補足】オリジナルの translator-sdaps-dictionary-English.dict の入手方法

Ubuntuなどでパッケージからインストールできる場合は、/usr/share/sdaps/tex/ からコピーすれば良いのですが、それができない場合にDockerイメージから抽出する方法をメモしておきます。

"docker cp"はイメージからのファイル抽出には使えないので、少々面倒ですが、次のような方法でオリジナルのファイルを抽出することができます。

コンテナ内部のファイルをローカルファイルシステムにコピーする
## sdapsコマンドを実行する("-rm"オプションは付けない)
$ docker run yasuhiroabe/sdaps-ja:latest

## コンテナIDを確認する
$ docker ps -a |grep sdaps-ja
a9e5dcb2a026        yasuhiroabe/sdaps-ja:latest   "/run.sh --help"         17 seconds ago      Exited (0) 16 s
econds ago                       eloquent_haibt

## コンテナIDを利用して必要なファイルをコピーする
$ docker cp a9e5dcb2a026:/usr/share/sdaps/tex/translator-sdaps-dictionary-English.dict my-translator.dict

setupコマンド

回答票のTeXファイルを作成したら、sdapsコマンドにプロジェクト・ディレクトリを作成させます。事前にプロジェクト名でディレクトリを作成するとエラーになります。

setup実行例
$ make proj1-setup
sudo docker run --rm \
        -v `pwd`/dev.proj1:/proj \
        --name sdaps-ja \
        yasuhiroabe/sdaps-ja:ub2004-2 \
        setup \
        --add translator-sdaps-dictionary-English.dict \
        work/ example-ja.tex
コマンド実行時のメッセージ
This is XeTeX, Version 3.14159265-2.6-0.999991 (TeX Live 2019/Debian) (preloaded format=xelatex)
 restricted \write18 enabled.
entering extended mode
This is XeTeX, Version 3.14159265-2.6-0.999991 (TeX Live 2019/Debian) (preloaded format=xelatex)
 restricted \write18 enabled.
entering extended mode
...
Running xelatex now multiple times to generate the questionnaire.
Running xelatex now multiple imes to generate the questionnaire.
タイトル
Author: 作者
Date: 10.03.2013

指定したプロジェクト・ディレクトリ(dev.proj1/work/)の中に、questionnaire.pdf が配置されます。

この例では、translator-sdaps-dictionary-English.dictを指定しています。 (省略可能)
このファイルはプロジェクト・ディレクトリを作成すればコピーされますが、事前に入手したい場合には次のような方法で可能です。

addコマンド

質問票をスキャンし、TIFFマルチページ形式のファイル(この例では01.tif)をプロジェクト・ディレクトリに配置してから、addを実行します。

add実行例
$ make proj1-add
sudo docker run --rm \
        -v `pwd`/sdaps.proj:/proj \
        yasuhiroabe/sdaps-ja:ub2004-2 add work 01.tiff
コマンド実行時のメッセージ
Processing 01.tiff
Done

使用している機材では1ファイルに25ページ分の回答しか格納できないので、これを越える場合は複数回、addコマンドを実行します。

recognizeコマンド

回答シートの登録が終った時点で、その登録したシートを解析するフェーズです。

recognize
$ make proj1-recognize 
sudo docker run --rm \
        -v `pwd`/dev.proj1:/proj \
        yasuhiroabe/sdaps-ja:ub2004-2 \
        recognize work
コマンド実行時のメッセージ
Connection Error (Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory)
Connection Null
...
Warning: 1.tif, 1: Matrix not recognized.
Warning: No page number for page 1.tif, 1 exists.
Warning: Got a wrong survey ID (1.tif, 1)! It is None, but should be 2449560734.
Warning: 1.tif, 3: Matrix not recognized.
Warning: No page number for page 1.tif, 3 exists.
Warning: Got a wrong survey ID (1.tif, 3)! It is None, but should be 2449560734.
4 sheets
Processed 4 of 4 sheets, took 1.852894 seconds
‘‘‘

## report_texコマンド

解析した結果を元にレポートPDFファイルを抽出するために使用します。

```bash:report_tex実行例
$ make proj1-reporttex 
    sudo docker run --rm \
    -v `pwd`/dev.proj1:/proj \
    yasuhiroabe/sdaps-ja:ub2004-2 \
    report_tex work/ 
コマンド実行時のメッセージ
Unable to init server: Could not connect: Connection refused
Unable to init server: Could not connect: Connection refused
This is XeTeX, Version 3.14159265-2.6-0.999991 (TeX Live 2019/Debian) (preloaded format=xelatex)
 restricted \write18 enabled.
entering extended mode
...
Running xelatex now multiple times to generate the report.

処理が終るとプロジェクト・ディレクトリ(dev.proj1/work/)の中に、report_.pdfファイルが生成されています。
report_texコマンドのオプションに、
--create-tex*オプションがあり、TeXファイルを抽出する機能がありますが、これは/tmpに途中経過を出力するため、もし利用する場合には、適当なディレクトリを/tmpにマウントしてください。この例はGNUmakefile内の、proj2-reporttexタスクに記載しています。

report_1.pdfには次のように結果が出力されます。"Answers:", "Mean:", "Standard-Deviation:"などを日本語化したい場合には、translator-sdaps-dictionary-English.dict を変更してください。

image.png

csvコマンド

生データをCSV形式で抽出したい場合に利用します。レポートの内容が正しいか検証するために使用します。
Excelで偏差などを計算すると誤差の処理方法の違いから、微妙に違う値が表示されるなどするかもしれません。

csv実行例
$ make proj1-csv 
sudo docker run --rm \
   -v `pwd`/dev.proj1:/proj \
   yasuhiroabe/sdaps-ja:ub2004-2 \
   csv export work/ 

生成されたCSVファイルは、プロジェクト・ディレクトリの data_*.csv に出力されています。

dev.proj1/work/data_2.csvの内容
questionnaire_id,global_id,empty,valid,recognized,review,verified,1_review,1_1_review,1_1
None,None,0,1,1,,0,,,3
None,None,1,0,1,,0,,,-1
None,None,0,1,1,,0,,,4
None,None,1,0,1,,0,,,-1

主な利用例は以上です。

作業中に発生した問題

最後に作業中に遭遇した問題についてメモを残しておきます。興味のある方はどうぞ。

sdaps reportを実行するとエラーが発生する

コンテナの中から実行した時だけ、"Unable to init server: Could not connect: Connection refused"というメッセージが表示されます。

エラー発生時のコマンドライン
## あらかじめ dev.proj2/ には、質問票のTeXファイルと回答をsdaps addした20200310_survey/ディレクトリを配置しています
$ sudo docker run --rm -v `pwd`/dev.proj2:/proj \
        --name sdaps-ja \
        yasuhiroabe/sdaps-ja:ub2004-2 report 20200310_survey/

エラーのタイミングが不明だったので、起動スクリプトを作成し、straceで処理の様子を観察しました。

デバッグ用run.sh
#!/bin/bash

cd "${WORKING_DIR}"
strace sdaps "$@"

そこでメッセージが出力される

connect(6, {sa_family=AF_UNIX, sun_path=@"/home/sdaps/.cache/broadway1.socket"}, 38) = -1 ECONNREFUSED (Connection refused)

どうやら裏で画像イメージを処理するかなにかでロードしているライブラリが初期化処理で、Xサーバーに接続しようとして失敗しているように見えます。
sdapsがちゃんと実行できるローカル環境でもDISPLAY環境変数を稼動していない方に向けると失敗します。

エラーの再現
$ env DISPLAY="" sdaps report 20200310_survey
------------------------------------------------------------------------------
- SDAPS -- report
------------------------------------------------------------------------------
Unable to init server: Could not connect: Connection refused
Unable to init server: Could not connect: Connection refused

このため、DISPLAY環境変数をdocker runの際に--envオプションで追加することにしました。
Ubuntu 20.04のX serverはunix domain socketのみを開いているので(6000番ポートは閉じている)、/tmp/.X11-unixをmountしています。この辺りは、lsofの出力と参考情報にあるリンク先を参考にしています。

それでもDBus周りのエラーは残っていますが、とりあえずスルーすることにします。

次に発生したDBus周りのエラー
$ make proj2-report
sudo docker run --rm \
        -e DISPLAY=:0.0 \
        -v /tmp/.X11-unix:/tmp/.X11-unix \
        -v `pwd`/dev.proj2:/proj \
        --name sdaps-ja \
                sdaps-ja \
        report 20200310_survey/  

(sdaps:1): dbind-WARNING **: 13:41:40.375: Couldn't connect to accessibility bus: Failed to connect to socket 
/tmp/dbus-5MKrJQOOU3: Connection refused

なおX serverに接続しなくても、エラーのまま処理は正常に終了しているので、実際の利用時にはこれらの変数は設定していません。

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

GCPでMinecraftサーバー

はじめに

Minecraftのサーバーを、GCP(Google Cloud Platform)上にDockerで簡単に立てられないかってことで調べました。
最後に書くけど、Minecraftのライセンスがどうなっているのかよくわからないので、わかる方がいたらそっと教えてください。m(_ _)m

前提として、下記の知識がちょっと必要。

  • GCPの設定画面とかがちょっとわかる
  • linux(ubuntu)がちょっとわかる
  • dockerがちょっとわかる

GCE使うので、無料期間が終わっている人はGCEのお金がかかりますので、ご注意ください。無料期間中でも選択によってはかかるかも。

あとゲームが終わったらVM停止。ぜったい。

1.GCEの準備

GCE(Google Compute Engine)とは、GCPで提供するクラウド上の仮想マシン。GCP上ではVM インスタンスと書かれている。VMはバーチャルマシン。

1.1. インスタンスの作成

ほぼデフォルトのままで大丈夫だけど、3点変更。

1つ目が、マシンタイプを e2-medium (vCPU x2、メモリ 4GB) 以上にすること。
最初ケチって、e2-micro(vCPU x2、メモリ 1GB)にしたら、JavaのThreadがどうこう、ヒープメモリがどうこうというエラーが出ていた。(詳しくは割愛)
単純に大きくすることで解消。ただし4GBでも多少カクつく!余裕があればそれ以上もお試してください。私は余裕が・・・

2つ目は、気を付けるというかブートディスクのオペレーティング システムを Ubuntu にしました。ほかでもいいと思うけど試してません。

3つ目は、ネットワーキングのネットワーク タグ。minecraft-server とかにしておく。
これは、この次の手順でファイアウォールの穴を開けるときに指示します。

起動すると、VM インスタンスのページに作ったのが一覧表示(1件だけかもしれないけど)され、音楽の再生ボタンみたいな右向き三角が出てればOK。
そこの外部IPのところに表示されているIPアドレスが、外から接続する際のIPアドレス。少し発展的な内容ですが、このIPアドレスは、デフォルトでは エフェメラル という起動のたびに変わる設定です。固定にしたい場合は、ネットワーキングのネットワークインタフェースの外部 IPを エフェメラル から IPアドレスを生成 へ変更します。(たぶんちょっと追加料金かかる)

1.2. ファイアウォールに穴開け

GCE上のMinecraftのサーバーと、クライアントのデータやり取りは、ポート番号25565を使ってやる。なので、GCPのファイアウォールの25565番を開けてやる必要がある。
GCPのメニューのVPC ネットワークファイアウォールファイアウォール ルールを作成
名前は適当でよくて、変更点は2点。

1つ目は、ターゲットを minecraft-server へ。1.1.の3つ目で指定したやつです。

2つ目は、ソースIPの範囲を 0.0.0.0/0 へ。誰でも接続できますよっていうこと。接続できるIPアドレスを制限したい人はここで厳密に設定してください。

2. Dockerをインストール

作ったVM インスタンスに、Dockerをインストールします。
説明はざっくりとさせていただきます。

まずGCEのVM インスタンスの一覧から、SSHって書いてあるプルダウンの中のブラウザ ウィンドウで開くで黒い画面=SSH接続のコンソール画面を出します。そこから先はUbuntuで下記。

# Dockerインストール用のシェルをダウンロード
$ curl -fsSL get.docker.com -o get-docker.sh

# 実行
$ sudo sh get-docker.sh

# ユーザーをdockerグループに追加
$ sudo usermod -aG docker (ユーザー名)

最後のは、dockerコマンドを打つたびに sudo docker ~と入力するのが面倒なので、ユーザーをdockerグループに入れるという呪文です。SSH接続の再起動が必要なので、黒い画面を開きなおします。
docker version でバージョンが出たら、ここまで成功。

3.Minecraftをインストールと起動

インストールというか、Dockerコンテナを作るっていう話です。上記の続きから。

# データ用のフォルダを作って、権限を設定しておく
$ sudo mkdir /var/mc_data/
$ sudo chmod 777 /var/mc_data/

# MinecraftサーバーのDockerイメージを取得
$ docker pull itzg/minecraft-server

# Minecraftサーバー起動!
$ docker run -d -e EULA=TRUE -p 25565:25565 -v /var/mc_data:/data --name minecraft --restart always itzg/minecraft-server

これでサーバーの起動まで終了。
黒い画面は、右上のバツボタンで閉じていいです。

4. クライアントから接続

Minecraftのマルチプレイのダイレクト接続で、VMインスタンスの外部IPアドレスを指定することで入れます。

5. 終了(必須)

GCEは起動している時間に応じて課金されるので、週末遊んでその次の週末までやらない場合とか、やってない間は止めたいです。というか必須!その止め方。

GCEのVMインスタンスの一覧で、チェックボックスで選択して、音楽の停止ボタンみたいなので停止。
VMインスタンスの停止 という画面が出ます。パソコンでいうと、電源落とすという意味。

6. 再起動

また次の週末に起動する方法。

GCEのVMインスタンスの一覧で、チェックボックスで選択して、音楽の再生ボタンみたいなので起動。
パソコンでいうと電源オン。

VMの起動の後、Minecraftサーバーの時間にちょっと時間がかかります。30秒とか1分とかそれくらい。
待たずに起動すると、Minecraftの画面に下記のエラーが出ました。

サーバーへの接続に失敗しました。
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information:

ちょっとわかる人だと、VM起動とともにDockerコンテナも動き出すのか心配になりますが、起動します。大丈夫。

7.補足と疑問

7.1. Minecraft内の時間

サーバーが起動しててログインしてない間、Minecraft内の時間は進むのか、止まるのか。
かまどに木を1スタック突っ込んで燃やし、Minecraftは終了してみました。1個10秒かかるので64個は640秒で約10分です。無駄に誰もログインしていない状態で10分放置しました。

結果は、止まってた。誰も入ってないと時間が止まるのか。
うーん、無駄な時間を過ごしてしまった。けど知っておくべきことを知れてよかった。

よく考えてみると、マルチプレイでログインしてる別の人が離れたところにいる場合でも止まりそう。つまり、プレイヤーがいる周りだけ更新されていくということか。当たり前だったか。
(スポーンチャンクはどうなのか。非常に気になるけど未検証。)

7.2. RCON

実はまだよくわかっていないのですが、Minecraftサーバー用のコンソール機能がRCONと言われるもののようです。
ログインしている人のリストとか、キックとか、アイテムを与えるとか、ブロックを作るとか、神様みたいな感じです。チートな状態だと、入力できるコマンドかも。Minecraft console commands and cheats

サーバーを起動した状態(=Dockerが起動している状態)で実行可能です。
まずVM インスタンスのSSHの黒い画面を起動。
次に下記を入力で、指示できる状態に入ります。
(抜け方はわからないので、いつもCtrl+Cで抜けてます。)

$ docker exec -it minecraft rcon-cli

起動しているDockerコンテナの中に入って、rcon-cliというモジュールを実行するというもの。
下記のように、後ろにコマンド(例ではlistコマンド)を入れると、そのコマンドだけ実行して終わる。

$ docker exec -it minecraft rcon-cli list

上記を連続的に呼び出すようにshellを組めば、複数のコマンドをまとめたものとか、大きな建築物とかプログラムでできそうな感じですね。

7.3. Minecraftの料金

サーバーのexeを実行すると、サーバーの人だけは料金はかかり、そこへ接続する人はかからないという話をどこかで聞いた。(やってない)

今回の手順の場合はどうなんだろうか。ID/パスワードをどこかで聞かれるかなと思ってたけど、最終的に聞かれなかった。私はクライアントのMinecraftのライセンスを持っていて、普通に接続できていることがそれゆえなのか、なくてもできるのか、結局わからずじまいのままです。すみません。

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

Docker開発環境でCapybaraを使ったブラウザテスト環境を構築する

概要

docker開発環境でRSpecテスト環境を構築するやり方をまとめました。
初心者で独学なので間違っている部分やもっといいやり方があると思いますが、その時はご指摘頂けると嬉しいです。

以下の記事を参考にしました。
Rails on DockerでRSpecのSystem testをSelenium Dockerを使ってやってみた。

はじめに

以前、Dockerを使ったRails開発でブラウザテストが実行できないでブラウザテストのエラー解消の記事を投稿しましたが、
コメントを頂き、docker-composeを使ってchrome自体をサービスの一つとして動かせば、
Rails環境を汚さずに簡単にテストができるとアドバイスを頂きましたので試してみました。
ご指摘ありがとうございました!

1.docker-compose.ymlにchromeのサービスを追加

使用するイメージはChromeが最初からインストールされたものである、standalone-chromeを使います。

docker-compose.yml
version: '3'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/[app名]
    ports:
      - 3000:3000
    depends_on:
      - db
      - chrome # ←追加
    tty: true
    stdin_open: true
  db:
    image: mysql:5.7
    volumes:
      - db-volume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
 # ↓追加
  chrome:
    image: selenium/standalone-chrome:latest
    ports:
      - 4444:4444
 # ↑追加
volumes:
  db-volume:

2.RSpecの導入

rspec-railsのgemを追記します

Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.1'  # 追加
  gem 'factory_bot_rails', '~>4.11'
end

gemをインストールします。

$ docker-compose build

※ビルドした後はコンテナの再起動を忘れずに

RSpecのインストール

$ docker-compose run web rails g rspec:install

次に、インストールすると作成されるファイルの中に、"rails_helper.rb"に設定を記述していきます。
RSpec実行時にdocker-seleniumのコンテナのブラウザを使用するように設定します。

/spec/rails_helper.rb
#~
Capybara.register_driver :remote_chrome do |app|
  url = "http://chrome:4444/wd/hub"
  caps = ::Selenium::WebDriver::Remote::Capabilities.chrome(
    "goog:chromeOptions" => {
      "args" => [
        "no-sandbox",
        "headless",
        "disable-gpu",
        "window-size=1680,1050"
      ]
    }
  )
  Capybara::Selenium::Driver.new(app, browser: :remote, url: url, desired_capabilities: caps)
end

#~

RSpec.configure do |config|

  config.before(:each, type: :system) do
    driven_by :rack_test
  end

  config.before(:each, type: :system, js: true) do
    driven_by :remote_chrome
    Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
    Capybara.server_port = 4444
    Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
  end
#~
end

最後に.rspecを編集して、rails_helper.rbの設定を読み取るようにします。

.rspec
- --require spec_helper
+ --require rails_helper

以上です。

あとはテストを記述してテストを実行できるか確認してみます。

#コンテナ起動時
$ docker-compose exec web rspec [rspecテストファイルのpath]

テスト失敗時にブラウザのハードコピーを確認することができました。

スクリーンショット 2020-09-22 22.30.01.png

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

pleasanter+PostgreSQL+SSL+dockerで自動バックアップを作ってみた

概要

  • 前回記事の続きです。
  • 本格的にシステムを使う事を考えた場合、バックアップはちゃんと考えておく必要が有ります。
  • 今回は自動でバックアップできるようにシステム化しました。
  • 対応できるバックアップ種別は「Fullバックアップ」と「PITR(ポイント・イン・タイム・リカバリ)」です。
  • AWS S3の設定を入れておくことで、バックアップデータをS3に同期する事も出来ます。

コンテナ構成

バックアップ作業用にコンテナが追加になっています。
追加されたコンテナを下表に示します。
postgres-dbとcron-backupはDBの領域を共有しており、
PITRが使える状態になっています。

コンテナ名 概要
cron-backup バックアップ用クーロンコンテナ
postgres-db PostgreSQL DB
pleasanter-web PleasanterのWebシステム

バックアップスクリプト

自動バックアップ機構に使用されるスクリプトは以下となります。
これらのスクリプトはpcron-backupコンテナに配備されます。

スクリプト名 概要
/var/backup_sh/pg_rman.sh PITRを実行
/var/backup_sh/pg_dumpall.sh Full Backupを実行
/var/backup_sh/pg_dumpall.sh S3同期を実行

バックアップ設定

ディレクトリ構成

pcron-backupコンテナから見たディレクトリ構成し下表となります。
共有が〇となっているパスに関してはpostgres-dbコンテナと共有しています。

バックアップ結果のデータは「/var/db_backup」に集まってくるように出来ています。
このため、このディレクトリをコンテナ外の接続してバックアップを取得しておけば必要なコンテナの外側からバックアップは取れる状態になります。

パス名 概要 コンテナ間共有
/var/db_backup/PITR/ ポイント・イン・タイム・リカバリ用のバックアップディレクトリ
/var/db_backup/dumpall 全データバックアップ用のディレクトリ
/var/backup_sh バックアップ用Shell格納ディレクトリ
/var/ バックアップ用Shell格納ディレクトリ
/var/lib/postgresql/data/ postgresqlデータ領域
/var/lib/postgresql/arclog postgresqlWAL領域

取得頻度

バックの動作管理はcronにより制御されています。
該当cromの設定は「cron-backup\config\crontab」にあります。
初期状態では以下の指定になっています。
必要に応じて、対象時間を切り替えてください。

種別 頻度
全バックアップ 毎日午前3時に1回
PITR(ポイント・イン・タイム・リカバリ) 30分毎

バックアップの開始

これらバックアップスクリプトはDocker Composeを起動すると自動的に起動を開始します。
開始にあたり、何か特別な操作は不要です。

逆にバックアップを取りたくない場合、該当のコンテナを起動しないように

バックアップ設定 オプション機能 S3同期

概要

ここまでのバックアップ機能だけですと、何かあってコンテナが飛んだ時にデータを損失する危険性があります。
バックアップはどこか別の場所に確保しておく必要があります。
現代は、S3という便利なものかあるのでそこに自動同期するようにつくってあります。

有効化

AWS CLIの設定が存在する時に有効化されます。
有効化判定の対象となるパスし以下です。

「/root/.aws/config」

この設定ファイルはconfigとしてコンテナ内部にコピーさせるよりは、コンテナの外に置いておいてマウントさせるほうが楽です。
(以下の★の部分です。)

docker-compose.yml
  cron-backup:
    build:
      context: cron-backup/.
    volumes:
      - *APP_DB_data
      - *APP_DB_arclog
      # 自動バックアップされた結果は「/var/db_backup」に格納される。
      # コンテナの外からアクセスする場合は、このパスを外から見える所に配置しておく
      - db-backup:/var/db_backup
      # S3で自動バックアップする場合
      # aws cliの設定を以下パスに行う。
      # 存在しない場合はバックアップは行われない
      - ./cron-backup/config/aws-cli:/root/.aws/ ← ★

設定

ホストがWindows環境の場合、GITの設定によっては、設定ファイルがCRLFで取得される事があります。
設定ファイルをその状態でコンテナ内に持っていくと改行コードが合わなくて正しく動かないので、設定ファイルの改行コードの取り扱いには注意してください。

まず、AWS CLIの設定が必要です。
このあたりは一般的な設定なので、ご自分のアカウントから必要な情報を取得してください。

cron-backup\config\aws-cli\credentials
[default]
aws_access_key_id = アクセスキー
aws_secret_access_key = シークレットキー 

次に、バックアップ対象の設定を行います。
これはshell形式の設定となります。

cron-backup\config\aws-cli\S3Config.sh
#!/bin/bash

# --- S3 同期設定

# 同期対象となる S3 バケット名
export S3_TARGET_BUCKET_NAME={バケット名}

# 同期対象となる S3 ディレクトリ名
export S3_TARGET_DIRECTORY_NAME={ディレクトリ名}

実行タイミング

S3への同期はバックアップ処理が実行されたタイミングとなります。
設定が正しくできていれば、開始のために特別な設定は不要です。

セーフモード

S3への同期はaws cliの「rsync」コマンドのdeleteオプション付きで行われます。
このコマンドを用いた場合、同期先のディレクトリは同期元のディレクトリと同一になるように動作します。
ここで、同一とはつまり「同期元になくて同先先にあるファイルは消去される」という意味です。
新規に環境を作った直後に設定を間違えてこのバックアップが動いてしまうと、必要なデータが消えてしまい大変な事になります。

そこで、S3のバックアップ処理にはセーフモードが付いています。
セーフモードでは、S3の対象バケットの対象ディレクトリに既存のコンテナがもっているバックアップ系統とは異なるデータが確認された場合、上書きはせずに「ディレクトリ名-safe」というディレクトリを作ってそちら側にバックアップを行うという処理となります。
バックアップ系統の同一性確認には、バックアップ時に生成される「BackupFiles.sha256.7z」というファイルを参照して実施します。

基本的には、ユーザーはあまり気にする必要はありませんが、環境移行の時などは既存のバックアップを壊してしまわないように十分注意して実行してください。
また、初回バックアップ実施後は「ディレクトリ名-safe」のようなディレクトリが出来ていないか確認してください。


リストア

リストアに関しては、
バックアップデータの取得方法により戻し方が変わってきます。

全バックアップで取得した場合

以下、cron-backupコンテナで作業した事とします。
バックアップファイルは7z形式、かつ、暗号化されています。
適宜復元してください。
(暗号キーに関してはshellファイル「cron-backup\shell\pg_dumpall.sh」を参照してください)
以下コマンドは、復元されたファイルが「backup」という名称となっている事を前提としています。
全バックアップからの復元は以下コマンド一発で完了です。

 psql -h postgres-db -p 5432  -U postgres -f backup

PITR

PITRの場合、少しややこしいです。
PITRの場合、postgresが動いているとうまく復元できないため、
cron-backupコンテナだけ起動させます。

docker-compose up pleasanter-cron-backup

手順0 . データコピー

pleasanter-cron-backupコンテナで実施します。
復元に使用するデータを用意します。
復元に用いるデータは「/var/db_backup/PITR/」にコピーしてください。

手順1 . クーロン停止

pleasanter-cron-backupコンテナで実施します。
クーロンを普通に起動しておくとバックアップクーロンがデータのバックアップを開始してしまいます。
そこで、バックアップクーロン停止しておきます。

crontab -l > my_cron_backup.txt
crontab -r

手順2 . バックアップ済みデータ確認

pleasanter-cron-backupコンテナで実施します。
以下コマンドで取得済みのバックアップ一覧を表示します。

/usr/lib/postgresql/12/bin/pg_rman show  -B /var/db_backup/PITR/

コマンドを実行すると以下のようにバックアップとして戻すことが出来るタイミングの一覧が表示されます。

root@885777f50d56:~/out/cron-backup/shell# /usr/lib/postgresql/12/bin/pg_rman show  -B /var/db_backup/PITR/
=====================================================================
 StartTime           EndTime              Mode    Size   TLI  Status
=====================================================================
2020-09-22 21:44:35  2020-09-22 21:44:38  INCR    33kB     3  OK
2020-09-22 21:43:32  2020-09-22 21:43:35  INCR    33kB     3  OK
2020-09-22 21:40:54  2020-09-22 21:40:58  INCR    33kB     3  OK
2020-09-22 21:39:32  2020-09-22 21:39:35  INCR    33kB     3  OK
2020-09-22 21:38:47  2020-09-22 21:38:51  INCR    33kB     3  OK
2020-09-22 21:32:47  2020-09-22 21:36:18  FULL    61MB     3  OK

手順3 . リストア

pleasanter-cron-backupコンテナで実施します。
PITRの場合、戻し方には二つのパターンがあります。

最終バックのタイミングに戻す

以下コマンドを用います。

/usr/lib/postgresql/12/bin/pg_rman restore  -B /var/db_backup/PITR/ -D /var/lib/postgresql/data/

任意タイミングに戻す

任意タイミングに戻す場合、戻す対象の時間を指定する事が可能です。
コマンドは以下となり、「recovery-target-time」として対象時間を指定します。

/usr/lib/postgresql/12/bin/pg_rman restore  --recovery-target-time '2020-09-06 14:29:00'  -B /var/db_backup/PITR/ -D /var/lib/postgresql/data/

手順6 . クーロン戻し

pleasanter-cron-backupコンテナで実施します。
クーロンの設定を元に戻します。

crontab my_cron_backup.txt
crontab -l

DBの整合性チェック

ここの処理は「全バックアップ」、「PITR」のいずれから戻した場合においても共通で必要となります。
バックアップ処理ではシステム動作中にデータを抜いてきています。
このため、DB上に存在するセッション情報などが中途半端な状態で残っています。

以下コマンドを使って、DB上の不要なデータを一度クリーンします。
(docker ホストで実行します。)

docker ps | grep leasanter-web | cut -d' ' -f 1  | xargs -I {} docker exec {} cmdnetcore/codedefiner.sh

後処理

DBを戻したら後処理が必要です。

速やかなFUllバックアップ

動くことを確認したら速やかにFullバックアップを取りましょう。
以下コマンドを直接叩く事でFullバックアップの取得が可能です。
ただし、S3設定がされている場合、S3への同期も走るので、十分注意して実施してください。

「/var/backup_sh/pg_dumpall.sh」

PITRにおけるベースバックアップの再取得

バックアップから戻した後の場合、PITRではベースバックアップがそれまでに取得されているものと変わっている可能性があ要ります。
(PITRでは、ベースバックアップに差分を重ねるという取り方をするが、リストアによりベースバックアップと最新のDB状態がすれた場合、後続のバックアップ処理が正しく実施できなくなる。)
そこで、ベースバックアップの再取得が必要となります。

  1. 「/var/db_backup/PITR/」パスにPITRのバックアップデータがあります。これを移動させます。
  2. 「/var/backup_sh/pg_rman.sh」コマンドを使って、バックアップデータが空の状態で再度バックアップを実施します。(S3同期するので注意が必要)

参考

OSC北海道2014_JPUG資料
MastodonのPostgreSQLをpg_rmanを使ってバックアップする
pg_rman
pg_rmanを使ってみる
pg_rmanによるPostgreSQLの簡単バックアップ&リカバリ

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

docker help 日本語訳

docker help 実行時に表示されるドキュメントの日本語訳。

使用法:

docker [OPTIONS] COMMAND

自己完結型コンテナーランタイム

オプション:

  • --config string クライアント構成ファイルの場所(デフォルトは ~/.docker )
  • -c, --context string デーモンへの接続に使用するコンテキストの名前( DOCKER_HOST env var および docker context use で設定されたデフォルトのコンテキストをオーバーライドします)
  • -D, -debug デバッグモードを有効にする
  • -H, --host list 接続するデーモンソケット
  • -l, -log-level string ログレベルを設定します(デフォルトは info )
    • "debug"
    • "info"
    • "warn"
    • "error"
    • "fatal"
  • --tls --tlsverify によって指定された TLS を使用します。
  • --tlscacert string この CA のみが署名した信頼証明書(デフォルトは ~/.docker/ca.pem )
  • --tlscert string TLS 証明書ファイルへのパス(デフォルトは ~/.docker/cert.pem )
  • --tlskey string TLS キーファイルへのパス(デフォルトは ~/.docker/key.pem )
  • --tlsverify TLS を使用してリモートを確認する
  • -v, --version バージョン情報を出力して終了

管理コマンド:

  • app* Docker アプリケーション(Docker Inc., v0.8.0)
  • builder ビルドを管理する
  • buildx* BuildKit を使用してビルド(Docker Inc., v0.3.1-tp-docker)
  • checkpoint チェックポイントを管理する
  • config Docker 構成を管理する
  • container コンテナを管理する
  • context コンテキストを管理する
  • image イメージを管理する
  • manifest Docker イメージマニフェストとマニフェストリストを管理する
  • network ネットワークを管理する
  • node Swarm ノードを管理する
  • plugin プラグインを管理する
  • scan* Docker Scan(Docker Inc., v0.3.3)
  • secret Docker シークレットを管理する
  • service サービスを管理する
  • stack Docker スタックを管理する
  • swarm スウォームを管理する
  • system Docker を管理する
  • trust 信頼する Docker イメージを管理する
  • volume ボリュームを管理する

コマンド:

  • attach ローカルの標準入力、出力、およびエラーストリームを実行中のコンテナーにアタッチする
  • build Dockerfile からイメージをビルドする
  • commit 変更を加えたコンテナーから新しいイメージを作成する
  • cp コンテナーとローカルファイルシステム間でファイル / フォルダーをコピーする
  • create 新しいコンテナを作成する
  • deploy 新しいスタックをデプロイするか、既存のスタックを更新します
  • diff コンテナーのファイルシステム上のファイルまたはディレクトリへの変更を検出する
  • events サーバーからリアルタイムのイベントを取得する
  • exec 実行中のコンテナでコマンドを実行する
  • export コンテナーのファイルシステムを tar アーカイブとしてエクスポートする
  • history イメージの履歴を表示する
  • images イメージを一覧表示する
  • import tarball からコンテンツをインポートしてファイルシステムイメージを作成します
  • info システム全体の情報を表示する
  • inspect Docker オブジェクトに関する低レベルの情報を返す
  • kill 実行中の 1 つ以上のコンテナーを強制終了する
  • load tar アーカイブまたは STDIN からイメージを読み込む
  • login Docker レジストリにログインする
  • logout Docker レジストリからログアウトする
  • logs コンテナのログを取得する
  • pause 1 つ以上のコンテナ内のすべてのプロセスを一時停止します
  • port コンテナのポートマッピングを一覧表示、またはポートマッピングを指定する。
  • ps コンテナーの一覧表示
  • pull レジストリからイメージまたはリポジトリを取得する
  • push イメージまたはリポジトリをレジストリに登録する
  • rename コンテナーの名前を変更する
  • restart 1 つ以上のコンテナを再起動します
  • rm 1 つ以上のコンテナーを削除する
  • rmi 1 つまたは複数のイメージを削除する
  • run 新しいコンテナでコマンドを実行する
  • save 1 つ以上のイメージを tar アーカイブに保存します(デフォルトで STDOUT にストリーミングされます)
  • search Docker Hub でイメージを検索する
  • start 停止している 1 つ以上のコンテナーを起動する
  • stats コンテナのリソース使用状況統計のライブストリームを表示する
  • stop 実行中の 1 つ以上のコンテナーを停止する
  • tag SOURCE_IMAGE を参照するタグ TARGET_IMAGE を作成します
  • top コンテナの実行中のプロセスを表示する
  • unpause 1 つ以上のコンテナー内のすべてのプロセスの一時停止を解除します
  • update 1 つ以上のコンテナーの構成を更新する
  • version Dockerの バージョン情報を表示する
  • wait 1 つ以上のコンテナーが停止するまでブロックし、その終了コードを出力します

コマンドの詳細については docker COMMAND --help を実行してください。

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

Docker x Laravel phpMyAdmin を導入する

以前の記事(最強のLaravel開発環境をDockerを使って構築する【新編集版】)のコメントにてphpMyAdminを使用したいという要望がありましたので補足の記事を作成させていただきます。

手順

https://github.com/ucan-lab/docker-laravel

docker-compose.yml に phpMyAdmin のサービスを追加

docker-compose.yml
volumes:
  # 追記
  pma-session-store:

services:
  # 追記
  pma:
    image: phpmyadmin/phpmyadmin:5.0.2
    environment:
      - PMA_HOST=db
      - PMA_USER=root
      - PMA_PASSWORD=secret
    ports:
      - 8080:80
    volumes:
      - pma-session-store:/sessions

Dockerコンテナの構築

$ docker-compose up -d

phpMyAdmin へアクセス

http://127.0.0.1:8080

上記のURLへアクセスし、phpMyAdminの画面が表示されればokです。

ScreenShot 2020-09-22 19.11.42.png

ScreenShot 2020-09-22 19.11.46.png

補足

MySQL新認証プラグイン caching_sha2_password

私のdbコンテナの設定でMySQL8.0系で認証方式を新しいcaching_sha2_passwordに設定しています。phpMyAdminは5.0.1以降でないとcaching_sha2_passwordに対応していないのでタグで新しいバージョンを明示的に指定してます。latestが5系を指すようになったら外してもいいかもです。

蛇足

(MySQLのCLIやSequel Ace等のクライアントツールで特に不便がないのでがあるので個人的にはphpMyAdminは入れなくてもいいかなと思ってます)

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

Docker x Laravel phpMyAdmin のコンテナを構築する

以前の記事(最強のLaravel開発環境をDockerを使って構築する【新編集版】)のコメントにてphpMyAdminを使用したいという要望がありましたので補足の記事を作成させていただきます。

手順

https://github.com/ucan-lab/docker-laravel

docker-compose.yml に phpMyAdmin のサービスを追加

docker-compose.yml
volumes:
  # 追記
  pma-session-store:

services:
  # 追記
  pma:
    image: phpmyadmin/phpmyadmin:5.0.2
    environment:
      - PMA_HOST=db
      - PMA_USER=root
      - PMA_PASSWORD=secret
    ports:
      - 8080:80
    volumes:
      - pma-session-store:/sessions

Dockerコンテナの構築

$ docker-compose up -d

phpMyAdmin へアクセス

http://127.0.0.1:8080

上記のURLへアクセスし、phpMyAdminの画面が表示されればokです。

ScreenShot 2020-09-22 19.11.42.png

ScreenShot 2020-09-22 19.11.46.png

補足

MySQL新認証プラグイン caching_sha2_password

私のdbコンテナの設定でMySQL8.0系で認証方式を新しいcaching_sha2_passwordに設定しています。phpMyAdminは5.0.1以降でないとcaching_sha2_passwordに対応していないのでタグで新しいバージョンを明示的に指定してます。latestが5系を指すようになったら外してもいいかもです。

蛇足

(MySQLのCLIやSequel Ace等のクライアントツールで特に不便がないのでがあるので個人的にはphpMyAdminは入れなくてもいいかなと思ってます)

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

非ネット接続環境でのDockerのセットアップ

社内の開発環境等、非インターネット接続環境でのDocker Engineのセットアップ方法の作業メモ

前提環境

  • 検証用のため、AWS上に環境を準備。

利用AMI:RHEL-7.1_HVM-20150803-x86_64-1-Hourly2-GP2
インスタンスタイプ:t2.medium(2vCPU/4GiB)

RHEL7.1環境
Red Hat Enterprise Linux Server release 7.1 (Maipo)

Docker導入準備

インターネット接続環境であれば、以下手順に従い、yum installで一発だが、今回は非インターネット接続環境という前提の為、依存性を解決しつつ、必要なrpmを準備
http://docs.docker.jp/engine/installation/linux/rhel.html

  • Red Hat Customer PortalよりDocker Engineのパッケージ一式をダウンロード
必要RPM一覧
[root@ip-172-31-47-162 docker]# ls -ltr 
total 13100
-rw-r--r--. 1 ec2-user ec2-user   56232 Sep 22 06:16 docker-selinux-1.6.2-14.el7.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user 7969356 Sep 22 06:19 docker-1.6.2-14.el7.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  918432 Sep 22 06:20 lvm2-2.02.115-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  783492 Sep 22 06:22 lvm2-libs-2.02.115-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  214388 Sep 22 06:28 device-mapper-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  162532 Sep 22 06:28 device-mapper-event-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  155168 Sep 22 06:28 device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  265880 Sep 22 06:28 device-mapper-libs-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user 2869284 Sep 22 06:28 device-mapper-persistent-data-0.3.2-1.el7.x86_64.rpm
[root@ip-172-31-47-162 docker]#
  • まずは、Docker Engineのメインのパッケージである、「docker-1.6.2-14」をダウンロードの上、yum localinstallにて、依存性のあるパッケージを抽出。
  • Red Hat Customer Portalより必要なパッケージをダウンロードし、SCPにてAWS上のRHEL環境に転送。
  • 非インターネット接続環境とする為、EC2のセキュリティグループのアウトバウンドは、全て拒否設定。
  • デフォルトのrepo設定だと、以下エラーが出力され、localinstallすらできない(アウトバウンド拒否している為、デフォルトのrepoに問い合わせできない)為、設定変更。
エラー出力
[root@ip-172-31-47-162 docker]# yum localinstall ./*
Loaded plugins: amazon-id, rhui-lb
Examining ./container-selinux-2.10-2.el7.noarch.rpm: 2:container-selinux-2.10-2.el7.noarch
Marking ./container-selinux-2.10-2.el7.noarch.rpm to be installed
Examining ./docker-1.12.6-16.el7.x86_64.rpm: 2:docker-1.12.6-16.el7.x86_64
Marking ./docker-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./docker-client-1.12.6-16.el7.x86_64.rpm: 2:docker-client-1.12.6-16.el7.x86_64
Marking ./docker-client-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./docker-common-1.12.6-16.el7.x86_64.rpm: 2:docker-common-1.12.6-16.el7.x86_64
Marking ./docker-common-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./docker-rhel-push-plugin-1.12.6-16.el7.x86_64.rpm: 2:docker-rhel-push-plugin-1.12.6-16.el7.x86_64
Marking ./docker-rhel-push-plugin-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./oci-register-machine-0-3.11.gitdd0daef.el7.x86_64.rpm: 1:oci-register-machine-0-3.11.gitdd0daef.el7.x86_64
Marking ./oci-register-machine-0-3.11.gitdd0daef.el7.x86_64.rpm to be installed
Examining ./oci-systemd-hook-0.1.4-9.git671c428.el7.x86_64.rpm: 1:oci-systemd-hook-0.1.4-9.git671c428.el7.x86_64
Marking ./oci-systemd-hook-0.1.4-9.git671c428.el7.x86_64.rpm to be installed
Examining ./skopeo-containers-0.1.20-2.el7.x86_64.rpm: 1:skopeo-containers-0.1.20-2.el7.x86_64
Marking ./skopeo-containers-0.1.20-2.el7.x86_64.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package container-selinux.noarch 2:2.10-2.el7 will be installed
--> Processing Dependency: policycoreutils >= 2.5-11 for package: 2:container-selinux-2.10-2.el7.noarch
Could not contact CDS load balancer rhui2-cds01.ap-northeast-1.aws.ce.redhat.com, trying others.


Could not contact any CDS load balancers: rhui2-cds01.ap-northeast-1.aws.ce.redhat.com, rhui2-cds02.ap-northeast-1.aws.ce.redhat.com.
[root@ip-172-31-47-162 docker]#
repoの設定変更
[root@ip-172-31-47-162 yum.repos.d]# yum-config-manager --save --setopt=local-myrepository.skip_if_unavailable=true

Docker Engineのインストール

  • yum localinstallコマンドにてDocker Engineのインストール
インストールの実行
[root@ip-172-31-47-162 docker]# yum localinstall ./*
Loaded plugins: amazon-id, rhui-lb
Examining ./device-mapper-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-1.02.93-3.el7_1.2.x86_64.rpm as an update to 7:device-mapper-1.02.93-3.el7_1.1.x86_64
Examining ./device-mapper-event-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-event-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-event-1.02.93-3.el7_1.2.x86_64.rpm to be installed
Examining ./device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64.rpm to be installed
Examining ./device-mapper-libs-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-libs-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-libs-1.02.93-3.el7_1.2.x86_64.rpm as an update to 7:device-mapper-libs-1.02.93-3.el7_1.1.x86_64
Examining ./device-mapper-persistent-data-0.3.2-1.el7.x86_64.rpm: device-mapper-persistent-data-0.3.2-1.el7.x86_64
Marking ./device-mapper-persistent-data-0.3.2-1.el7.x86_64.rpm to be installed
Examining ./docker-1.6.2-14.el7.x86_64.rpm: docker-1.6.2-14.el7.x86_64
Marking ./docker-1.6.2-14.el7.x86_64.rpm to be installed
Examining ./docker-selinux-1.6.2-14.el7.x86_64.rpm: docker-selinux-1.6.2-14.el7.x86_64
Marking ./docker-selinux-1.6.2-14.el7.x86_64.rpm to be installed
Examining ./lvm2-2.02.115-3.el7_1.2.x86_64.rpm: 7:lvm2-2.02.115-3.el7_1.2.x86_64
Marking ./lvm2-2.02.115-3.el7_1.2.x86_64.rpm to be installed
Examining ./lvm2-libs-2.02.115-3.el7_1.2.x86_64.rpm: 7:lvm2-libs-2.02.115-3.el7_1.2.x86_64
Marking ./lvm2-libs-2.02.115-3.el7_1.2.x86_64.rpm to be installed
Skipping: ./old, filename does not end in .rpm.
Resolving Dependencies
--> Running transaction check
---> Package device-mapper.x86_64 7:1.02.93-3.el7_1.1 will be updated
---> Package device-mapper.x86_64 7:1.02.93-3.el7_1.2 will be an update
---> Package device-mapper-event.x86_64 7:1.02.93-3.el7_1.2 will be installed
---> Package device-mapper-event-libs.x86_64 7:1.02.93-3.el7_1.2 will be installed
---> Package device-mapper-libs.x86_64 7:1.02.93-3.el7_1.1 will be updated
---> Package device-mapper-libs.x86_64 7:1.02.93-3.el7_1.2 will be an update
---> Package device-mapper-persistent-data.x86_64 0:0.3.2-1.el7 will be installed
---> Package docker.x86_64 0:1.6.2-14.el7 will be installed
---> Package docker-selinux.x86_64 0:1.6.2-14.el7 will be installed
---> Package lvm2.x86_64 7:2.02.115-3.el7_1.2 will be installed
---> Package lvm2-libs.x86_64 7:2.02.115-3.el7_1.2 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

========================================================================================================================
 Package                        Arch    Version               Repository                                           Size
========================================================================================================================
Installing:
 device-mapper-event            x86_64  7:1.02.93-3.el7_1.2   /device-mapper-event-1.02.93-3.el7_1.2.x86_64        37 k
 device-mapper-event-libs       x86_64  7:1.02.93-3.el7_1.2   /device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64   27 k
 device-mapper-persistent-data  x86_64  0.3.2-1.el7           /device-mapper-persistent-data-0.3.2-1.el7.x86_64    17 M
 docker                         x86_64  1.6.2-14.el7          /docker-1.6.2-14.el7.x86_64                          32 M
 docker-selinux                 x86_64  1.6.2-14.el7          /docker-selinux-1.6.2-14.el7.x86_64                  25 k
 lvm2                           x86_64  7:2.02.115-3.el7_1.2  /lvm2-2.02.115-3.el7_1.2.x86_64                     1.8 M
 lvm2-libs                      x86_64  7:2.02.115-3.el7_1.2  /lvm2-libs-2.02.115-3.el7_1.2.x86_64                2.2 M
Updating:
 device-mapper                  x86_64  7:1.02.93-3.el7_1.2   /device-mapper-1.02.93-3.el7_1.2.x86_64             189 k
 device-mapper-libs             x86_64  7:1.02.93-3.el7_1.2   /device-mapper-libs-1.02.93-3.el7_1.2.x86_64        293 k

Transaction Summary
========================================================================================================================
Install  7 Packages
Upgrade  2 Packages

Total size: 54 M
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Updating   : 7:device-mapper-1.02.93-3.el7_1.2.x86_64                                                            1/11 
  Updating   : 7:device-mapper-libs-1.02.93-3.el7_1.2.x86_64                                                       2/11 
  Installing : 7:device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64                                                 3/11 
  Installing : 7:device-mapper-event-1.02.93-3.el7_1.2.x86_64                                                      4/11 
  Installing : 7:lvm2-libs-2.02.115-3.el7_1.2.x86_64                                                               5/11 
  Installing : docker-selinux-1.6.2-14.el7.x86_64                                                                  6/11 
  Installing : device-mapper-persistent-data-0.3.2-1.el7.x86_64                                                    7/11 
  Installing : 7:lvm2-2.02.115-3.el7_1.2.x86_64                                                                    8/11 
  Installing : docker-1.6.2-14.el7.x86_64                                                                          9/11 
  Cleanup    : 7:device-mapper-1.02.93-3.el7_1.1.x86_64                                                           10/11 
  Cleanup    : 7:device-mapper-libs-1.02.93-3.el7_1.1.x86_64                                                      11/11 
  Verifying  : device-mapper-persistent-data-0.3.2-1.el7.x86_64                                                    1/11 
  Verifying  : 7:lvm2-2.02.115-3.el7_1.2.x86_64                                                                    2/11 
  Verifying  : 7:device-mapper-libs-1.02.93-3.el7_1.2.x86_64                                                       3/11 
  Verifying  : 7:device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64                                                 4/11 
  Verifying  : docker-1.6.2-14.el7.x86_64                                                                          5/11 
  Verifying  : 7:device-mapper-event-1.02.93-3.el7_1.2.x86_64                                                      6/11 
  Verifying  : 7:lvm2-libs-2.02.115-3.el7_1.2.x86_64                                                               7/11 
  Verifying  : 7:device-mapper-1.02.93-3.el7_1.2.x86_64                                                            8/11 
  Verifying  : docker-selinux-1.6.2-14.el7.x86_64                                                                  9/11 
  Verifying  : 7:device-mapper-1.02.93-3.el7_1.1.x86_64                                                           10/11 
  Verifying  : 7:device-mapper-libs-1.02.93-3.el7_1.1.x86_64                                                      11/11 

Installed:
  device-mapper-event.x86_64 7:1.02.93-3.el7_1.2             device-mapper-event-libs.x86_64 7:1.02.93-3.el7_1.2        
  device-mapper-persistent-data.x86_64 0:0.3.2-1.el7         docker.x86_64 0:1.6.2-14.el7                               
  docker-selinux.x86_64 0:1.6.2-14.el7                       lvm2.x86_64 7:2.02.115-3.el7_1.2                           
  lvm2-libs.x86_64 7:2.02.115-3.el7_1.2                     

Updated:
  device-mapper.x86_64 7:1.02.93-3.el7_1.2                 device-mapper-libs.x86_64 7:1.02.93-3.el7_1.2                

Complete!
[root@ip-172-31-47-162 docker]# 

インストール後の稼働確認

  • docker engineの起動&ステータス確認
DockerEngineの起動&起動確認
[root@ip-172-31-47-162 docker]# systemctl start docker 
[root@ip-172-31-47-162 docker]# 
[root@ip-172-31-47-162 docker]# systemctl status docker 
docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled)
   Active: active (running) since Tue 2020-09-22 06:29:23 EDT; 10s ago
     Docs: http://docs.docker.com
 Main PID: 18149 (docker)
   CGroup: /system.slice/docker.service
           └─18149 /usr/bin/docker -d --selinux-enabled --add-registry registry.access.redhat.com

Sep 22 06:29:16 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:16-04:00" lev..."
Sep 22 06:29:22 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:22-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal systemd[1]: Started Docker Application Container E...e.
Hint: Some lines were ellipsized, use -l to show in full.
[root@ip-172-31-47-162 docker]#
[root@ip-172-31-47-162 docker]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@ip-172-31-47-162 docker]# 
  • 外部接続できない為、docker searchコマンドは失敗(想定通り)
エラー出力
[root@ip-172-31-47-162 docker]# docker search hello-world
FATA[0127] Error response from daemon: Get https://index.docker.io/v1/search?q=hello-world: dial tcp 52.55.43.248:443: connection timed out 
[root@ip-172-31-47-162 docker]# 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

非ネット接続環境でのDocker Engineのセットアップ

社内の開発環境等、非インターネット接続環境でのDocker Engineのセットアップ方法の作業メモ

前提環境

  • 検証用のため、AWS上に環境を準備。

利用AMI:RHEL-7.1_HVM-20150803-x86_64-1-Hourly2-GP2
インスタンスタイプ:t2.medium(2vCPU/4GiB)

RHEL7.1環境
Red Hat Enterprise Linux Server release 7.1 (Maipo)

Docker導入準備

インターネット接続環境であれば、以下手順に従い、yum installで一発だが、今回は非インターネット接続環境という前提の為、依存性を解決しつつ、必要なrpmを準備
http://docs.docker.jp/engine/installation/linux/rhel.html

  • Red Hat Customer PortalよりDocker Engineのパッケージ一式をダウンロード
必要RPM一覧
[root@ip-172-31-47-162 docker]# ls -ltr 
total 13100
-rw-r--r--. 1 ec2-user ec2-user   56232 Sep 22 06:16 docker-selinux-1.6.2-14.el7.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user 7969356 Sep 22 06:19 docker-1.6.2-14.el7.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  918432 Sep 22 06:20 lvm2-2.02.115-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  783492 Sep 22 06:22 lvm2-libs-2.02.115-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  214388 Sep 22 06:28 device-mapper-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  162532 Sep 22 06:28 device-mapper-event-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  155168 Sep 22 06:28 device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  265880 Sep 22 06:28 device-mapper-libs-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user 2869284 Sep 22 06:28 device-mapper-persistent-data-0.3.2-1.el7.x86_64.rpm
[root@ip-172-31-47-162 docker]#
  • まずは、Docker Engineのメインのパッケージである、「docker-1.6.2-14」をダウンロードの上、yum localinstallにて、依存性のあるパッケージを抽出。
  • 新しいDocker Engineバージョンだと、依存性地獄で面倒なので、あえて古いバージョン(RHEL7.1と親和性高そうなもの)を選択。。。
  • Red Hat Customer Portalより必要なパッケージをダウンロードし、SCPにてAWS上のRHEL環境に転送。
  • 非インターネット接続環境とする為、EC2のセキュリティグループのアウトバウンドは、全て拒否設定。(これにより、EC2からインターネット接続は不可。)
  • デフォルトのrepo設定だと、以下エラーが出力され、localinstallすらできない(アウトバウンド拒否している為、デフォルトのrepoに問い合わせできない)為、設定変更。
エラー出力
[root@ip-172-31-47-162 docker]# yum localinstall ./*
Loaded plugins: amazon-id, rhui-lb
Examining ./container-selinux-2.10-2.el7.noarch.rpm: 2:container-selinux-2.10-2.el7.noarch
Marking ./container-selinux-2.10-2.el7.noarch.rpm to be installed
Examining ./docker-1.12.6-16.el7.x86_64.rpm: 2:docker-1.12.6-16.el7.x86_64
Marking ./docker-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./docker-client-1.12.6-16.el7.x86_64.rpm: 2:docker-client-1.12.6-16.el7.x86_64
Marking ./docker-client-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./docker-common-1.12.6-16.el7.x86_64.rpm: 2:docker-common-1.12.6-16.el7.x86_64
Marking ./docker-common-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./docker-rhel-push-plugin-1.12.6-16.el7.x86_64.rpm: 2:docker-rhel-push-plugin-1.12.6-16.el7.x86_64
Marking ./docker-rhel-push-plugin-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./oci-register-machine-0-3.11.gitdd0daef.el7.x86_64.rpm: 1:oci-register-machine-0-3.11.gitdd0daef.el7.x86_64
Marking ./oci-register-machine-0-3.11.gitdd0daef.el7.x86_64.rpm to be installed
Examining ./oci-systemd-hook-0.1.4-9.git671c428.el7.x86_64.rpm: 1:oci-systemd-hook-0.1.4-9.git671c428.el7.x86_64
Marking ./oci-systemd-hook-0.1.4-9.git671c428.el7.x86_64.rpm to be installed
Examining ./skopeo-containers-0.1.20-2.el7.x86_64.rpm: 1:skopeo-containers-0.1.20-2.el7.x86_64
Marking ./skopeo-containers-0.1.20-2.el7.x86_64.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package container-selinux.noarch 2:2.10-2.el7 will be installed
--> Processing Dependency: policycoreutils >= 2.5-11 for package: 2:container-selinux-2.10-2.el7.noarch
Could not contact CDS load balancer rhui2-cds01.ap-northeast-1.aws.ce.redhat.com, trying others.


Could not contact any CDS load balancers: rhui2-cds01.ap-northeast-1.aws.ce.redhat.com, rhui2-cds02.ap-northeast-1.aws.ce.redhat.com.
[root@ip-172-31-47-162 docker]#
repoの設定変更
[root@ip-172-31-47-162 yum.repos.d]# yum-config-manager --save --setopt=local-myrepository.skip_if_unavailable=true

Docker Engineのインストール

  • yum localinstallコマンドにてDocker Engineのインストール
インストールの実行
[root@ip-172-31-47-162 docker]# yum localinstall ./*
Loaded plugins: amazon-id, rhui-lb
Examining ./device-mapper-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-1.02.93-3.el7_1.2.x86_64.rpm as an update to 7:device-mapper-1.02.93-3.el7_1.1.x86_64
Examining ./device-mapper-event-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-event-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-event-1.02.93-3.el7_1.2.x86_64.rpm to be installed
Examining ./device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64.rpm to be installed
Examining ./device-mapper-libs-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-libs-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-libs-1.02.93-3.el7_1.2.x86_64.rpm as an update to 7:device-mapper-libs-1.02.93-3.el7_1.1.x86_64
Examining ./device-mapper-persistent-data-0.3.2-1.el7.x86_64.rpm: device-mapper-persistent-data-0.3.2-1.el7.x86_64
Marking ./device-mapper-persistent-data-0.3.2-1.el7.x86_64.rpm to be installed
Examining ./docker-1.6.2-14.el7.x86_64.rpm: docker-1.6.2-14.el7.x86_64
Marking ./docker-1.6.2-14.el7.x86_64.rpm to be installed
Examining ./docker-selinux-1.6.2-14.el7.x86_64.rpm: docker-selinux-1.6.2-14.el7.x86_64
Marking ./docker-selinux-1.6.2-14.el7.x86_64.rpm to be installed
Examining ./lvm2-2.02.115-3.el7_1.2.x86_64.rpm: 7:lvm2-2.02.115-3.el7_1.2.x86_64
Marking ./lvm2-2.02.115-3.el7_1.2.x86_64.rpm to be installed
Examining ./lvm2-libs-2.02.115-3.el7_1.2.x86_64.rpm: 7:lvm2-libs-2.02.115-3.el7_1.2.x86_64
Marking ./lvm2-libs-2.02.115-3.el7_1.2.x86_64.rpm to be installed
Skipping: ./old, filename does not end in .rpm.
Resolving Dependencies
--> Running transaction check
---> Package device-mapper.x86_64 7:1.02.93-3.el7_1.1 will be updated
---> Package device-mapper.x86_64 7:1.02.93-3.el7_1.2 will be an update
---> Package device-mapper-event.x86_64 7:1.02.93-3.el7_1.2 will be installed
---> Package device-mapper-event-libs.x86_64 7:1.02.93-3.el7_1.2 will be installed
---> Package device-mapper-libs.x86_64 7:1.02.93-3.el7_1.1 will be updated
---> Package device-mapper-libs.x86_64 7:1.02.93-3.el7_1.2 will be an update
---> Package device-mapper-persistent-data.x86_64 0:0.3.2-1.el7 will be installed
---> Package docker.x86_64 0:1.6.2-14.el7 will be installed
---> Package docker-selinux.x86_64 0:1.6.2-14.el7 will be installed
---> Package lvm2.x86_64 7:2.02.115-3.el7_1.2 will be installed
---> Package lvm2-libs.x86_64 7:2.02.115-3.el7_1.2 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

========================================================================================================================
 Package                        Arch    Version               Repository                                           Size
========================================================================================================================
Installing:
 device-mapper-event            x86_64  7:1.02.93-3.el7_1.2   /device-mapper-event-1.02.93-3.el7_1.2.x86_64        37 k
 device-mapper-event-libs       x86_64  7:1.02.93-3.el7_1.2   /device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64   27 k
 device-mapper-persistent-data  x86_64  0.3.2-1.el7           /device-mapper-persistent-data-0.3.2-1.el7.x86_64    17 M
 docker                         x86_64  1.6.2-14.el7          /docker-1.6.2-14.el7.x86_64                          32 M
 docker-selinux                 x86_64  1.6.2-14.el7          /docker-selinux-1.6.2-14.el7.x86_64                  25 k
 lvm2                           x86_64  7:2.02.115-3.el7_1.2  /lvm2-2.02.115-3.el7_1.2.x86_64                     1.8 M
 lvm2-libs                      x86_64  7:2.02.115-3.el7_1.2  /lvm2-libs-2.02.115-3.el7_1.2.x86_64                2.2 M
Updating:
 device-mapper                  x86_64  7:1.02.93-3.el7_1.2   /device-mapper-1.02.93-3.el7_1.2.x86_64             189 k
 device-mapper-libs             x86_64  7:1.02.93-3.el7_1.2   /device-mapper-libs-1.02.93-3.el7_1.2.x86_64        293 k

Transaction Summary
========================================================================================================================
Install  7 Packages
Upgrade  2 Packages

Total size: 54 M
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Updating   : 7:device-mapper-1.02.93-3.el7_1.2.x86_64                                                            1/11 
  Updating   : 7:device-mapper-libs-1.02.93-3.el7_1.2.x86_64                                                       2/11 
  Installing : 7:device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64                                                 3/11 
  Installing : 7:device-mapper-event-1.02.93-3.el7_1.2.x86_64                                                      4/11 
  Installing : 7:lvm2-libs-2.02.115-3.el7_1.2.x86_64                                                               5/11 
  Installing : docker-selinux-1.6.2-14.el7.x86_64                                                                  6/11 
  Installing : device-mapper-persistent-data-0.3.2-1.el7.x86_64                                                    7/11 
  Installing : 7:lvm2-2.02.115-3.el7_1.2.x86_64                                                                    8/11 
  Installing : docker-1.6.2-14.el7.x86_64                                                                          9/11 
  Cleanup    : 7:device-mapper-1.02.93-3.el7_1.1.x86_64                                                           10/11 
  Cleanup    : 7:device-mapper-libs-1.02.93-3.el7_1.1.x86_64                                                      11/11 
  Verifying  : device-mapper-persistent-data-0.3.2-1.el7.x86_64                                                    1/11 
  Verifying  : 7:lvm2-2.02.115-3.el7_1.2.x86_64                                                                    2/11 
  Verifying  : 7:device-mapper-libs-1.02.93-3.el7_1.2.x86_64                                                       3/11 
  Verifying  : 7:device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64                                                 4/11 
  Verifying  : docker-1.6.2-14.el7.x86_64                                                                          5/11 
  Verifying  : 7:device-mapper-event-1.02.93-3.el7_1.2.x86_64                                                      6/11 
  Verifying  : 7:lvm2-libs-2.02.115-3.el7_1.2.x86_64                                                               7/11 
  Verifying  : 7:device-mapper-1.02.93-3.el7_1.2.x86_64                                                            8/11 
  Verifying  : docker-selinux-1.6.2-14.el7.x86_64                                                                  9/11 
  Verifying  : 7:device-mapper-1.02.93-3.el7_1.1.x86_64                                                           10/11 
  Verifying  : 7:device-mapper-libs-1.02.93-3.el7_1.1.x86_64                                                      11/11 

Installed:
  device-mapper-event.x86_64 7:1.02.93-3.el7_1.2             device-mapper-event-libs.x86_64 7:1.02.93-3.el7_1.2        
  device-mapper-persistent-data.x86_64 0:0.3.2-1.el7         docker.x86_64 0:1.6.2-14.el7                               
  docker-selinux.x86_64 0:1.6.2-14.el7                       lvm2.x86_64 7:2.02.115-3.el7_1.2                           
  lvm2-libs.x86_64 7:2.02.115-3.el7_1.2                     

Updated:
  device-mapper.x86_64 7:1.02.93-3.el7_1.2                 device-mapper-libs.x86_64 7:1.02.93-3.el7_1.2                

Complete!
[root@ip-172-31-47-162 docker]# 

インストール後の稼働確認

  • docker engineの起動&ステータス確認
DockerEngineの起動&起動確認
[root@ip-172-31-47-162 docker]# systemctl start docker 
[root@ip-172-31-47-162 docker]# 
[root@ip-172-31-47-162 docker]# systemctl status docker 
docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled)
   Active: active (running) since Tue 2020-09-22 06:29:23 EDT; 10s ago
     Docs: http://docs.docker.com
 Main PID: 18149 (docker)
   CGroup: /system.slice/docker.service
           └─18149 /usr/bin/docker -d --selinux-enabled --add-registry registry.access.redhat.com

Sep 22 06:29:16 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:16-04:00" lev..."
Sep 22 06:29:22 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:22-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal systemd[1]: Started Docker Application Container E...e.
Hint: Some lines were ellipsized, use -l to show in full.
[root@ip-172-31-47-162 docker]#
[root@ip-172-31-47-162 docker]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@ip-172-31-47-162 docker]# 
  • 外部接続できない為、docker searchコマンドは失敗(想定通り)
エラー出力
[root@ip-172-31-47-162 docker]# docker search hello-world
FATA[0127] Error response from daemon: Get https://index.docker.io/v1/search?q=hello-world: dial tcp 52.55.43.248:443: connection timed out 
[root@ip-172-31-47-162 docker]# 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

非インターネット接続環境でのDocker Engineのセットアップ

社内の開発環境等、非インターネット接続環境でのDocker Engineのセットアップ方法の作業メモ

前提環境

  • 検証用のため、AWS上に環境を準備。

利用AMI:RHEL-7.1_HVM-20150803-x86_64-1-Hourly2-GP2
インスタンスタイプ:t2.medium(2vCPU/4GiB)

RHEL7.1環境
Red Hat Enterprise Linux Server release 7.1 (Maipo)

Docker導入準備

インターネット接続環境であれば、以下手順に従い、yum installで一発だが、今回は非インターネット接続環境という前提の為、依存性を解決しつつ、必要なrpmを準備
http://docs.docker.jp/engine/installation/linux/rhel.html

  • Red Hat Customer PortalよりDocker Engineのパッケージ一式をダウンロード
必要RPM一覧
[root@ip-172-31-47-162 docker]# ls -ltr 
total 13100
-rw-r--r--. 1 ec2-user ec2-user   56232 Sep 22 06:16 docker-selinux-1.6.2-14.el7.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user 7969356 Sep 22 06:19 docker-1.6.2-14.el7.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  918432 Sep 22 06:20 lvm2-2.02.115-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  783492 Sep 22 06:22 lvm2-libs-2.02.115-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  214388 Sep 22 06:28 device-mapper-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  162532 Sep 22 06:28 device-mapper-event-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  155168 Sep 22 06:28 device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user  265880 Sep 22 06:28 device-mapper-libs-1.02.93-3.el7_1.2.x86_64.rpm
-rw-r--r--. 1 ec2-user ec2-user 2869284 Sep 22 06:28 device-mapper-persistent-data-0.3.2-1.el7.x86_64.rpm
[root@ip-172-31-47-162 docker]#
  • まずは、Docker Engineのメインのパッケージである、「docker-1.6.2-14」をダウンロードの上、yum localinstallにて、依存性のあるパッケージを抽出。
  • 新しいDocker Engineバージョンだと、依存性地獄で面倒なので、あえて古いバージョン(RHEL7.1と親和性高そうなもの)を選択。。。
  • Red Hat Customer Portalより必要なパッケージをダウンロードし、SCPにてAWS上のRHEL環境に転送。
  • 非インターネット接続環境とする為、EC2のセキュリティグループのアウトバウンドは、全て拒否設定。(これにより、EC2からインターネット接続は不可。)
  • デフォルトのrepo設定だと、以下エラーが出力され、localinstallすらできない(アウトバウンド拒否している為、デフォルトのrepoに問い合わせできない)為、設定変更。
エラー出力
[root@ip-172-31-47-162 docker]# yum localinstall ./*
Loaded plugins: amazon-id, rhui-lb
Examining ./container-selinux-2.10-2.el7.noarch.rpm: 2:container-selinux-2.10-2.el7.noarch
Marking ./container-selinux-2.10-2.el7.noarch.rpm to be installed
Examining ./docker-1.12.6-16.el7.x86_64.rpm: 2:docker-1.12.6-16.el7.x86_64
Marking ./docker-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./docker-client-1.12.6-16.el7.x86_64.rpm: 2:docker-client-1.12.6-16.el7.x86_64
Marking ./docker-client-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./docker-common-1.12.6-16.el7.x86_64.rpm: 2:docker-common-1.12.6-16.el7.x86_64
Marking ./docker-common-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./docker-rhel-push-plugin-1.12.6-16.el7.x86_64.rpm: 2:docker-rhel-push-plugin-1.12.6-16.el7.x86_64
Marking ./docker-rhel-push-plugin-1.12.6-16.el7.x86_64.rpm to be installed
Examining ./oci-register-machine-0-3.11.gitdd0daef.el7.x86_64.rpm: 1:oci-register-machine-0-3.11.gitdd0daef.el7.x86_64
Marking ./oci-register-machine-0-3.11.gitdd0daef.el7.x86_64.rpm to be installed
Examining ./oci-systemd-hook-0.1.4-9.git671c428.el7.x86_64.rpm: 1:oci-systemd-hook-0.1.4-9.git671c428.el7.x86_64
Marking ./oci-systemd-hook-0.1.4-9.git671c428.el7.x86_64.rpm to be installed
Examining ./skopeo-containers-0.1.20-2.el7.x86_64.rpm: 1:skopeo-containers-0.1.20-2.el7.x86_64
Marking ./skopeo-containers-0.1.20-2.el7.x86_64.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package container-selinux.noarch 2:2.10-2.el7 will be installed
--> Processing Dependency: policycoreutils >= 2.5-11 for package: 2:container-selinux-2.10-2.el7.noarch
Could not contact CDS load balancer rhui2-cds01.ap-northeast-1.aws.ce.redhat.com, trying others.


Could not contact any CDS load balancers: rhui2-cds01.ap-northeast-1.aws.ce.redhat.com, rhui2-cds02.ap-northeast-1.aws.ce.redhat.com.
[root@ip-172-31-47-162 docker]#
repoの設定変更
[root@ip-172-31-47-162 yum.repos.d]# yum-config-manager --save --setopt=local-myrepository.skip_if_unavailable=true

Docker Engineのインストール

  • yum localinstallコマンドにてDocker Engineのインストール
インストールの実行
[root@ip-172-31-47-162 docker]# yum localinstall ./*
Loaded plugins: amazon-id, rhui-lb
Examining ./device-mapper-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-1.02.93-3.el7_1.2.x86_64.rpm as an update to 7:device-mapper-1.02.93-3.el7_1.1.x86_64
Examining ./device-mapper-event-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-event-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-event-1.02.93-3.el7_1.2.x86_64.rpm to be installed
Examining ./device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64.rpm to be installed
Examining ./device-mapper-libs-1.02.93-3.el7_1.2.x86_64.rpm: 7:device-mapper-libs-1.02.93-3.el7_1.2.x86_64
Marking ./device-mapper-libs-1.02.93-3.el7_1.2.x86_64.rpm as an update to 7:device-mapper-libs-1.02.93-3.el7_1.1.x86_64
Examining ./device-mapper-persistent-data-0.3.2-1.el7.x86_64.rpm: device-mapper-persistent-data-0.3.2-1.el7.x86_64
Marking ./device-mapper-persistent-data-0.3.2-1.el7.x86_64.rpm to be installed
Examining ./docker-1.6.2-14.el7.x86_64.rpm: docker-1.6.2-14.el7.x86_64
Marking ./docker-1.6.2-14.el7.x86_64.rpm to be installed
Examining ./docker-selinux-1.6.2-14.el7.x86_64.rpm: docker-selinux-1.6.2-14.el7.x86_64
Marking ./docker-selinux-1.6.2-14.el7.x86_64.rpm to be installed
Examining ./lvm2-2.02.115-3.el7_1.2.x86_64.rpm: 7:lvm2-2.02.115-3.el7_1.2.x86_64
Marking ./lvm2-2.02.115-3.el7_1.2.x86_64.rpm to be installed
Examining ./lvm2-libs-2.02.115-3.el7_1.2.x86_64.rpm: 7:lvm2-libs-2.02.115-3.el7_1.2.x86_64
Marking ./lvm2-libs-2.02.115-3.el7_1.2.x86_64.rpm to be installed
Skipping: ./old, filename does not end in .rpm.
Resolving Dependencies
--> Running transaction check
---> Package device-mapper.x86_64 7:1.02.93-3.el7_1.1 will be updated
---> Package device-mapper.x86_64 7:1.02.93-3.el7_1.2 will be an update
---> Package device-mapper-event.x86_64 7:1.02.93-3.el7_1.2 will be installed
---> Package device-mapper-event-libs.x86_64 7:1.02.93-3.el7_1.2 will be installed
---> Package device-mapper-libs.x86_64 7:1.02.93-3.el7_1.1 will be updated
---> Package device-mapper-libs.x86_64 7:1.02.93-3.el7_1.2 will be an update
---> Package device-mapper-persistent-data.x86_64 0:0.3.2-1.el7 will be installed
---> Package docker.x86_64 0:1.6.2-14.el7 will be installed
---> Package docker-selinux.x86_64 0:1.6.2-14.el7 will be installed
---> Package lvm2.x86_64 7:2.02.115-3.el7_1.2 will be installed
---> Package lvm2-libs.x86_64 7:2.02.115-3.el7_1.2 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

========================================================================================================================
 Package                        Arch    Version               Repository                                           Size
========================================================================================================================
Installing:
 device-mapper-event            x86_64  7:1.02.93-3.el7_1.2   /device-mapper-event-1.02.93-3.el7_1.2.x86_64        37 k
 device-mapper-event-libs       x86_64  7:1.02.93-3.el7_1.2   /device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64   27 k
 device-mapper-persistent-data  x86_64  0.3.2-1.el7           /device-mapper-persistent-data-0.3.2-1.el7.x86_64    17 M
 docker                         x86_64  1.6.2-14.el7          /docker-1.6.2-14.el7.x86_64                          32 M
 docker-selinux                 x86_64  1.6.2-14.el7          /docker-selinux-1.6.2-14.el7.x86_64                  25 k
 lvm2                           x86_64  7:2.02.115-3.el7_1.2  /lvm2-2.02.115-3.el7_1.2.x86_64                     1.8 M
 lvm2-libs                      x86_64  7:2.02.115-3.el7_1.2  /lvm2-libs-2.02.115-3.el7_1.2.x86_64                2.2 M
Updating:
 device-mapper                  x86_64  7:1.02.93-3.el7_1.2   /device-mapper-1.02.93-3.el7_1.2.x86_64             189 k
 device-mapper-libs             x86_64  7:1.02.93-3.el7_1.2   /device-mapper-libs-1.02.93-3.el7_1.2.x86_64        293 k

Transaction Summary
========================================================================================================================
Install  7 Packages
Upgrade  2 Packages

Total size: 54 M
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Updating   : 7:device-mapper-1.02.93-3.el7_1.2.x86_64                                                            1/11 
  Updating   : 7:device-mapper-libs-1.02.93-3.el7_1.2.x86_64                                                       2/11 
  Installing : 7:device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64                                                 3/11 
  Installing : 7:device-mapper-event-1.02.93-3.el7_1.2.x86_64                                                      4/11 
  Installing : 7:lvm2-libs-2.02.115-3.el7_1.2.x86_64                                                               5/11 
  Installing : docker-selinux-1.6.2-14.el7.x86_64                                                                  6/11 
  Installing : device-mapper-persistent-data-0.3.2-1.el7.x86_64                                                    7/11 
  Installing : 7:lvm2-2.02.115-3.el7_1.2.x86_64                                                                    8/11 
  Installing : docker-1.6.2-14.el7.x86_64                                                                          9/11 
  Cleanup    : 7:device-mapper-1.02.93-3.el7_1.1.x86_64                                                           10/11 
  Cleanup    : 7:device-mapper-libs-1.02.93-3.el7_1.1.x86_64                                                      11/11 
  Verifying  : device-mapper-persistent-data-0.3.2-1.el7.x86_64                                                    1/11 
  Verifying  : 7:lvm2-2.02.115-3.el7_1.2.x86_64                                                                    2/11 
  Verifying  : 7:device-mapper-libs-1.02.93-3.el7_1.2.x86_64                                                       3/11 
  Verifying  : 7:device-mapper-event-libs-1.02.93-3.el7_1.2.x86_64                                                 4/11 
  Verifying  : docker-1.6.2-14.el7.x86_64                                                                          5/11 
  Verifying  : 7:device-mapper-event-1.02.93-3.el7_1.2.x86_64                                                      6/11 
  Verifying  : 7:lvm2-libs-2.02.115-3.el7_1.2.x86_64                                                               7/11 
  Verifying  : 7:device-mapper-1.02.93-3.el7_1.2.x86_64                                                            8/11 
  Verifying  : docker-selinux-1.6.2-14.el7.x86_64                                                                  9/11 
  Verifying  : 7:device-mapper-1.02.93-3.el7_1.1.x86_64                                                           10/11 
  Verifying  : 7:device-mapper-libs-1.02.93-3.el7_1.1.x86_64                                                      11/11 

Installed:
  device-mapper-event.x86_64 7:1.02.93-3.el7_1.2             device-mapper-event-libs.x86_64 7:1.02.93-3.el7_1.2        
  device-mapper-persistent-data.x86_64 0:0.3.2-1.el7         docker.x86_64 0:1.6.2-14.el7                               
  docker-selinux.x86_64 0:1.6.2-14.el7                       lvm2.x86_64 7:2.02.115-3.el7_1.2                           
  lvm2-libs.x86_64 7:2.02.115-3.el7_1.2                     

Updated:
  device-mapper.x86_64 7:1.02.93-3.el7_1.2                 device-mapper-libs.x86_64 7:1.02.93-3.el7_1.2                

Complete!
[root@ip-172-31-47-162 docker]# 

インストール後の稼働確認

  • docker engineの起動&ステータス確認
DockerEngineの起動&起動確認
[root@ip-172-31-47-162 docker]# systemctl start docker 
[root@ip-172-31-47-162 docker]# 
[root@ip-172-31-47-162 docker]# systemctl status docker 
docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled)
   Active: active (running) since Tue 2020-09-22 06:29:23 EDT; 10s ago
     Docs: http://docs.docker.com
 Main PID: 18149 (docker)
   CGroup: /system.slice/docker.service
           └─18149 /usr/bin/docker -d --selinux-enabled --add-registry registry.access.redhat.com

Sep 22 06:29:16 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:16-04:00" lev..."
Sep 22 06:29:22 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:22-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal docker[18149]: time="2020-09-22T06:29:23-04:00" lev..."
Sep 22 06:29:23 ip-172-31-47-162.ap-northeast-1.compute.internal systemd[1]: Started Docker Application Container E...e.
Hint: Some lines were ellipsized, use -l to show in full.
[root@ip-172-31-47-162 docker]#
[root@ip-172-31-47-162 docker]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@ip-172-31-47-162 docker]# 
  • 外部接続できない為、docker searchコマンドは失敗(想定通り)
エラー出力
[root@ip-172-31-47-162 docker]# docker search hello-world
FATA[0127] Error response from daemon: Get https://index.docker.io/v1/search?q=hello-world: dial tcp 52.55.43.248:443: connection timed out 
[root@ip-172-31-47-162 docker]# 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Express+PostgreSQL+SequelizeをDockerで構築してみる【後編】

前回

https://qiita.com/rockguitar67/items/b644a63b3e39cc1fcaea

はい続きです。

③DB周りの設定

コンテナ内のExpress環境においてDB設定がなされているファイルがあります。
ここでdocker-compose.ymlで設定したDBへのアクセス情報が明記されています。

db_client.js
module.exports = {
    pg_client: function () {
        const { Client } = require('pg')

        const client = new Client({
            user: process.env.DB_USER,
            host: process.env.DB_HOST,
            port: process.env.DB_PORT,
            database: process.env.DB_NAME
        })
        return client
    },
  };

一応現状でもDBにアクセス自体はできると思います。
routes内のindex.jsを見てみましょう!

'URL/'にGETでアクセスした時にどういった挙動をするかを書きます。
先ほどのsb_client.jsを読み取って、DBとの接続を可能にしています。

routes/index.js
router.get('/', function (req, res, next) {
  const client = require("../db_client").pg_client()

  client.connect()
     .then(() => console.log("success!!"))
     .then(() => client.query("select * from chat order by timestamp desc"))
     .then(function (results) {
      console.table(results.rows)
       res.render('index', { result: results.rows })
     })

しかし6行目を見ていただくと、DB処理をSQL文で呼び出しています。
これでもSQLの勉強としては良いのですが、複数のテーブルを用意して、それらを繋ぎ合わせるリレーションなどの処理を行う際はもっと楽なORMを活用します。

④ORMの活用

オブジェクト関係マッピング(英: Object-relational mapping、O/RM、ORM)とは、データベースとオブジェクト指向プログラミング言語の間の非互換なデータを変換するプログラミング技法である。 wikipedia参照

Node.jsを使用する際にORMとしてSequelizeを活用します。

Terminal
# npm install -g sequelize sequelize-cli

# sequelize-cli init

この時点で作業ディレクトリにconfig.jsonやmodelディレクトリが生成されます。

config

./config/config.json
{
  "development": {
    "username": "postgres",
    "password": null,
    "database": "mydatabase",
    "host": "database",
    "dialect": "postgres",
    "operatorsAliases": false
  },

config.jsonでhostに127.0.0.1を指定するのが一般的だそうですが、Dockerの場合だとmigrationの時点で、DBにアクセスできないよ、とエラーを吐くことがあります。その為docker-compose.ymlで設定したDB_HOST(=database)をそのまま活用します。

とりあえず作成するテーブルとカラム情報を決めて、DBを作成します!

Terminal
# sequelize-cli model:generate --name user --attributes firstName:string,lastName:string,email:string

# sequelize-cli db:migrate

migration

migrationが完了すると、DBのカラム情報がmigrationフォルダ内に表示されます。

./migration/日付-create-user.js
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      firstName: {
        type: Sequelize.STRING
      },
      lastName: {
        type: Sequelize.STRING
      },
      email: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('users');
  }
};

model

migrationが完了すると、Modelに入力したDBのカラム情報が表示されます。
これを確認できたら一応完了です。

./model/user.js
user.init({
    firstName: DataTypes.STRING,
    lastName: DataTypes.STRING,
    email: DataTypes.STRING
  }, {
    sequelize,
    modelName: 'user',
  });

model/index.jsや今回作成したmodel/user.jsはリレーション設定やアソシエーションなどで編集しますが、この時点ではノータッチです。

ユーザー登録→ユーザー表示の一連の流れ

簡単にユーザー登録アプリでも作ります。

https://github.com/LostGeneration1999/Express_PostgreSQL_ORM

フォームからユーザー:藤川球児を入力して表示させました。

スクリーンショット 2020-09-22 18.04.27.png

スクリーンショット 2020-09-22 18.04.41.png

#参考記事

https://qiita.com/markusveeyola/items/64875c9507d5fa32884e

PostgreSQLへのアクセス
https://qiita.com/yusuke-ka/items/448843020c0406363ba5

ORM関連
https://qiita.com/izszzz/items/31d448c501d24d31c846

ORM関連
https://qiita.com/KoKeCross/items/144949ba03e5138fc6d5

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

Express+PostgreSQL+SequelizeをDockerで構築してみる【前編】

前説

将来的にはフロントエンドはVue、バックエンドはExpressのような構成を目指します。
まずはバックエンドでExpress+PostgreSQL+Sequelizeでの環境構築です!

①Dockerでコンテナ動作まで

初期ファイル構成

-Dockerfile
-docker-compose.yml
-app
|-- package.json

Dockerfile

Dockefile
# イメージ指定
FROM node:latest

# 環境変数設定
ENV NODE_ENV="development"

# 作業ディレクトリ作成&設定
WORKDIR /src

COPY ./app /src

RUN npm install

docker-compose.yml

ここでNode.jsのExpress(サーバーサイド)コンテナの構造とDBコンテナの構造を設計します。

  • ポート番号は5432が一般的です。
  • Volumesではコンテナを破棄しても、データを永続化できます。その為データをコンテナ外に保存します。
docker-compose.yml
version: '3'
services:
  app:
  # Dockerfile保存場所
    build:
      context: ./  
    depends_on:
      - database
    image: n-app
    #volumes設定
    volumes:
     - "./app:/src"
    # コンテナ名
    container_name: n-app
    # ポート接続
    ports:                          
      - 3000:5000
    environment:
      PORT: 5000
      DB_USER: postgres
      DB_HOST: database
      DB_PORT: 5432
      DB_NAME: mydatabase
    tty: true

  database:
    image: postgres:12.3
    volumes:
      - ./init-sql:/docker-entrypoint-initdb.d:ro
    environment:
      POSTGRES_DB: mydatabase
      TZ: "Asia/Tokyo"
      POSTGRES_HOST_AUTH_METHOD: trust

package.json

自分用です。
Volumesを設定することにより、コンテナ上でInstallしたパッケージもホスト上・コンテナ上にも保存されます。コンテナを破棄した場合もVolumesを設定することにより、package.jsonをもとに'npm install'で破棄したコンテナの環境を復元できます。

  • scripts内では"node 〇〇"のコマンドの'〇〇'の部分を設定します。 現状./bin/wwwはExpressの雛形ファイルを生成しないと作成されませんので、注意が必要です。
app/package.json
{
  "name": "myapp",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www",
  },
  "dependencies": {
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "ejs": "~2.5.7",
    "express": "~4.16.0",
    "http-errors": "^1.6.3",
    "morgan": "~1.9.0",
    "nodemon": "^2.0.4",
    "pg": "*",
    "sequelize": "^6.3.5",
    "sequelize-cli": "^6.2.0"
  }
}

自分は以下のサイトを参考にしました。
以下のサイトの方のgithubからcloneして、必要な情報を追加しました。
あらかじめExpressのテンプレートが整っていたので、大変便利でした。

https://qiita.com/tamoco/items/caffca436546a1a5fcc8

ではDockerを使ってコンテナを動かしましょう。

Terminal
$ docker-compose build

Building app
Step 1/5 : FROM node:10.12
 ---> a2b9536415c2
Step 2/5 : ENV NODE_ENV="development"
 ---> Using cache
 ---> 40f981aef1ce
Step 3/5 : WORKDIR /src
 ---> Using cache
 ---> ec233d742a63
Step 4/5 : COPY ./app /src
 ---> Using cache
 ---> 88f269307e53
Step 5/5 : RUN npm install
 ---> Using cache
 ---> b22a8c36f08e

$ docker-compose up -d

$ docker-compose ps

      Name                     Command              State           Ports
----------------------------------------------------------------------------------
n-app               node                            Up      0.0.0.0:3000->5000/tcp
ta-app_database_1   docker-entrypoint.sh postgres   Up      5432/tcp

$ docker exec -it n-app bash

root@f195575a066f:/src# 

上記のところで構築したコンテナに入ることができました。

②Express環境構築

ExpressとはNode.js上で動作するWebアプリのMVC型フレームワークです。
自分の場合は偉大なる先人様のリポジトリからCloneしたため、あらかじめExpressの雛形が揃っていました。

Expressの雛形を生成したい場合はこんな感じでしょうか。

# npm install express-generator -g

1. viewをpugファイルで作成したい場合(Default)
# express --view=pug myapp

viewをejsファイルで作成したい場合
2. express -e myapp 

次回

https://qiita.com/rockguitar67/items/0020d734201632077cb5

参考文献

Docker-Expressの構築
https://qiita.com/tamoco/items/caffca436546a1a5fcc8

https://gitlab.com/tamoco-mocomoco/study-docker-compose/-/tree/master/app/routes

https://qiita.com/yoshiplum/items/129e7ad1ffc3a02b9eb2

Docker-Volumesについて
https://qiita.com/gounx2/items/23b0dc8b8b95cc629f32

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

IKS + Db2 on IBM Cloud で DBアクセスアプリを動かしてみた(7.WebSphere Liberty コンテナの準備)

はじめに

IKS + Db2 on IBM Cloud で DBアクセスアプリを動かしてみた」の 第7回です。
ここでは、 コンテナの準備ついて記載します。

実施内容は以下の通りです。

  • WebSphere Liberty コンテナの取得
  • 関連ファイルの配置
  • Docker ファイルの作成・ビルド
  • イメージの IBM Cloud Container Registry への登録

ベースのコンテナイメージとして、 WebSphere Liberty アプリケーションサーバーを利用します。
正確には Open Liberty で、サポートはありませんが無償で検証等で利用することができます。

WebSphere Liberty コンテナの取得

ベースとなる Liberty イメージは Docker Hub から取得します。
IBM Cloud CLI を導入した Linux を使って実施します。(Docker も導入されているはずです)

Docker Hub から 「WebSphere-liberty」で検索すると
Liberty のイメージがヒットします。

61.png

内容を見ると、kernel というタグがあることがわかります。
また、イメージの使い方についても簡単な説明がありますので、一通り目を通しておきます。
(後述する、ユーザーID なども記載されています)

Docker 導入・起動済みの Linux 上から以下のコマンドで WebSphere-Liberty のイメージを取得します。

# docker pull websphere-liberty:kernel
kernel: Pulling from library/websphere-liberty
5d9821c94847: Pull complete
a610eae58dfc: Pull complete
a40e0eb9f140: Pull complete
ce03bf3de33a: Pull complete
d26a401e3cfc: Pull complete
7c8d5d75e559: Pull complete
deaa1a0c4db8: Pull complete
bd803d95ded0: Pull complete
6a3c56e2964a: Pull complete
ae3986011977: Pull complete
a55f77d5aa37: Pull complete
299a2589f823: Pull complete
Digest: sha256:9312eecbfe9d85677857eb40a55cc90c2ccd32005dad2f6a6cbfc4bef5dfbdb3
Status: Downloaded newer image for websphere-liberty:kernel
docker.io/library/websphere-liberty:kernel

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
websphere-liberty   kernel              878137168ed8        5 days ago          311MB

これで、 WebSphere-Liberty のイメージが取得できました。簡単ですね。

関連ファイルの配置

さて、 取得済みの WebSphere-Liberty のイメージをベースに、
第6回で作成したアプリケーションや各種設定なども含めたイメージを作成します。
その準備として、必要なファイルを用意します。

作業用ディレクトリ(図中 "." )以下に ツリー上にファイルを配置します。
(作業用ディレクトリ内のディレクトリ構成は違っていても構いません。後述の DockerFile 作成時にコンテナ内の必要な場所にコピーすることになります。

62.png

以下に、ファイルとその内容について補足していきます。

DockerFile

これは、次の章で記載しますのでここでは割愛します。

LibertyCounter.war

これは、第6回で作成した war ファイルを sftp 等で配置します。(手順略)

db2jcc4.jar

Db2 にアクセスするための JDBC ドライバーです。
DB2 JDBC Driver Versions and Downloads から取得します。 バージョンは、 IBM Cloud でオーダーした Db2 に合わせて v11.1 の物を用います。
(特殊なことはしませんので、多少バージョンが違うものでも稼働すると思います。)

ダウンロードの詳細な手順は割愛しますが、 IBM ID が必要になりますのでご留意ください。
2020/09 時点では、ダウンロードできるファイル名は 「v11.1.4fp5_jdbc_sqlj.tar.gz」になりますが、
そのファイルを何度か展開し、 中にある db2jcc4.jar ファイルを取得します。 他のものは不要です。

server.xml

これは、WebSphere-Liberty のメインの設定ファイルです。
この中で各種設定を行っています。 まず全文を記載したのち、個別部分に補足を入れます。
下記のもののオリジナルのファイルを入手したい場合、
WebSphere-Liberty イメージからコンテナを1つ生成し、その中の /config 以下から取得してください。

<?xml version="1.0" encoding="UTF-8"?>
<server description="Default server">

    <!-- Enable features -->
    <featureManager>
        <feature>jndi-1.0</feature>
        <feature>webProfile-8.0</feature>
    </featureManager>

    <!--For a user registry configuration, configure your user registry. For example, configure a basic user registry using the
        basicRegistry element. Specify your own user name below in the name attribute of the user element. For the password,
        generate an encoded password using bin/securityUtility encode and add it in the password attribute of the user element.
        Then uncomment the user element. -->
    <basicRegistry id="basic" realm="BasicRealm">
        <!-- <user name="yourUserName" password="" />  -->
    </basicRegistry>

    <!-- To allow access to this server from a remote client host="*" has been added to the following element -->
    <httpEndpoint id="defaultHttpEndpoint"
                  host="*"
                  httpPort="9080"
                  httpsPort="9443" />

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>

    <dataSource id="dataSource01" jndiName="jdbc/sample" type="javax.sql.ConnectionPoolDataSource" containerAuthDataRef="dbuser" recoveryAuthDataRef="dbuser">
        <properties.db2.jcc
            serverName="${env.DB_SERVERNAME}"
            portNumber="${env.DB_PORT}"
            databaseName="${env.DB_DBNAME}"
        />
        <jdbcDriver>
            <library>
                <fileset dir="${DB2_JCC_DRIVER_PATH}" includes="db2jcc4.jar"/>
            </library>
        </jdbcDriver>
        <connectionManager minPoolSize="1" maxPoolSize="2" purgePolicy="EntirePool">
        </connectionManager>
    </dataSource>

    <authData id="dbuser" user="${env.DB_USERNAME}" password="${env.DB_PASSWORD}">
    </authData>

</server>

<feature> 部分では、利用する機能を指定します。 Web系の簡単なアプリケーションであれば webProfile-8.0 があれば大丈夫です。(また、他に必要なものがあれば、依存関係に基づき自動的にロードされます)

    <featureManager>
        <feature>jndi-1.0</feature>
        <feature>webProfile-8.0</feature>
    </featureManager>

httpEndpoint では使用するポートを指定しています。
今回は HTTP で 9080 ポートにアクセスします。

    <httpEndpoint id="defaultHttpEndpoint"
                  host="*"
                  httpPort="9080"
                  httpsPort="9443" />

以下の設定は データソースの設定です。
JNDI 名として、 jdbc/sample を記載(アプリケーション側でハードコードしたものです。ここでもハードコード…(外に出し忘れました。。。))
env. から始まる変数は環境変数から取得します。
${env.DB_SERVERNAME} : DB_SERVERNAME 環境変数から DBサーバーの名前を取得します
${env.DB_PORT} : DB_PORT 環境変数から DB のポート番号を取得します。
${env.DB_DBNAME} : DB_DBNAME 環境変数から DB名を取得します。

    <dataSource id="dataSource01" jndiName="|" type="javax.sql.ConnectionPoolDataSource" containerAuthDataRef="dbuser" recoveryAuthDataRef="dbuser">
        <properties.db2.jcc
            serverName="${env.DB_SERVERNAME}"
            portNumber="${env.DB_PORT}"
            databaseName="${env.DB_DBNAME}"
        />

次に JDBC Driver の設定です。
変数のうち、 env. ではないものは、 次に説明する server.env ファイルから取得します。
${DB2_JCC_DRIVER_PATH} : JDBC Driver ファイル (db2jcc4.jar) のコンテナ内でのパスを server.env から取得します。

minPoolSize="1" maxPoolSize="2" : DB接続プールを最小 1, 最大 2 に設定します。
IBM Cloud の無料 Db2 は最大接続数が 30 のため、最大を 10 などに設定していると、コンテナが増えたときにすぐ最大接続数に到達してエラーになります。そのため、低めの 2 に設定しています。

        <jdbcDriver>
            <library>
                <fileset dir="${DB2_JCC_DRIVER_PATH}" includes="db2jcc4.jar"/>
            </library>
        </jdbcDriver>
        <connectionManager minPoolSize="1" maxPoolSize="2" purgePolicy="EntirePool">
        </connectionManager>

2つ上のボックスで、 dbuser という形で(ファイル内で)参照している DB関連のユーザー情報です。
これも、 env. を使い、環境変数から DBユーザー名とパスワードを取得しています。

    <authData id="dbuser" user="${env.DB_USERNAME}" password="${env.DB_PASSWORD}">

変数についてまとめると、以下のような感じです。

変数 指定方法 取得先
DBサーバー名 env.DB_SERVERNAME 環境変数 DB_SERVERNAME
DBポート番号 env.DB_PORT 環境変数 DB_PORT
DB名 env.DB_DBNAME 環境変数 DB_DBNAME
DBユーザー名 env.DB_USERNAME 環境変数 DB_USERNAME
DBユーザーのパスワード env.DB_PASSWORD 環境変数 DB_PASSWORD
JDBC ドライバーパス DB2_JCC_DRIVER_PATH server.env ファイルの DB2_JCC_DRIVER_PATH
JNDI名 jdbc/sample (ハードコード) - (変数化し忘れ)

server.env

今回、server.env ファイルは JDBC ドライバのパスを指定しているだけです。
他にも同じようなやり方で情報を渡すことが可能です。
変更が多そうなものは環境変数として kubernetes から渡し、イメージとして変更する必要が無いものは server.env で指定すればよいでしょう。

server.env
DB2_JCC_DRIVER_PATH=/config/jdbc/

これで DockerFile 以外の物の配置は完了したことになります。

Dockerfile

次に、 Dockerfile と docker build コマンドでイメージを作成します。
まず、 Dockerfile の内容を確認しましょう。 この Dockerfile の基本は、 Docker Hub 上の
WebSphere-Liberty イメージの説明ページに記載されています。

FROM : 先に pull したイメージを指定します。
LABEL maintainer : 作った人のメールアドレスを指定します。(なければ無いで構いません)

ADD : ディレクトリや圧縮ファイル等を指定の場所に追加します。 ここでは ./files 以下を /config 以下に追加しています。また、あわせてオーナーを 1001 に変更しています(1001 は WebSphere-Liberty ベースイメージで指定されています)
COPY : LibertyCounter.war ファイルを /config/dropins にコピーし、オーナーを変更しています。

※WebSphere-Liberty では、 (設定次第ではありますが) dropins にアプリケーションを入れれば展開・デプロイされます。

configure.sh : これは WebSphere-Liberty イメージに付属のもので、最終的に必要となる WebSphere-Liberty のモジュール等をダウンロードし、起動させるスクリプトです。

Dockerfile
FROM docker.io/websphere-liberty:kernel
LABEL maintainer "shimauma@example.com"

ADD     --chown=1001:0 ./files /config
COPY    --chown=1001:0 ./war/LibertyCounter.war /config/dropins
RUN     configure.sh

Dockerfile の詳細は割愛します。(Web に多くの情報があると思います)

Dockerfile 作成後、それをビルドしてイメージを作成します。
-t で イメージ名とタグを指定しています。 "." はカレントディレクトリの Dockerfile をビルドする指定です。

ビルド
# ls
Dockerfile  files  war

# docker build -t liberty-counter:v3.0 .

Sending build context to Docker daemon  3.879MB
Step 1/5 : FROM docker.io/websphere-liberty:kernel
 ---> 878137168ed8
Step 2/5 : LABEL maintainer "shimauma@example.com"
 ---> Running in 1b88bab5c511
Removing intermediate container 1b88bab5c511
 ---> c4d48a0967a9
Step 3/5 : ADD  --chown=1001:0 ./files /config
 ---> 524464dc8c9f
Step 4/5 : COPY --chown=1001:0 ./war/LibertyCounter.war /config/dropins
 ---> be9224862fcf
Step 5/5 : RUN  configure.sh
 ---> Running in 8072633d8513
Removing intermediate container 8072633d8513
 ---> 11424458a589
Successfully built 11424458a589
Successfully tagged liberty-counter:v3.0

これでビルド完了です。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
liberty-counter     v3.0                11424458a589        48 seconds ago      459MB
websphere-liberty   kernel              878137168ed8        5 days ago          311MB

IBM Cloud container registry への登録

作成したイメージを IBM Cloud container registry へ登録します。
具体的には、 イメージ名に IBM Cloud container registry を付与し、push する、という流れになります。

まず、第2回で説明した手順で、IBM Cloud にログインします。(手順省略)
次に、第4回で説明した手順 で、イメージを登録します。

イメージ登録は以下のように行います。
まず、tag を付けます。

# docker tag liberty-counter:v3.0 jp.icr.io/shimauma_zzzzz/default/liberty-counter:v3.0

# docker images
REPOSITORY                                         TAG                 IMAGE ID            CREATED             SIZE
jp.icr.io/shimauma_zzzzz/default/liberty-counter   v3.0                11424458a589        17 minutes ago      459MB
liberty-counter                                    v3.0                11424458a589        17 minutes ago      459MB
websphere-liberty                                  kernel              878137168ed8        5 days ago          311MB

次に push します。

# docker push jp.icr.io/shimauma_zzzzz/default/liberty-counter:v3.0
The push refers to repository [jp.icr.io/shimauma_zzzzz/default/liberty-counter]
438065068251: Pushed
3bf39480c5d8: Pushed
055ed22e3425: Pushed
bfd7e29956e1: Pushed
dda1b0da9873: Pushed
73bca3f685ab: Pushed
045898917c82: Pushed
ea2e902881eb: Pushed
96471ed8874f: Pushed
39f28991b87f: Pushed
e243b6bd9c42: Pushed
8553a689df1b: Pushed
a2d674c9d7ed: Pushed
4ad5df11bd98: Pushed
6effd95c47f2: Pushed
v3.0: digest: sha256:9ea8239c910e2eb7b490822b1463fd9f624442d65a5ea06f4e3cbc89e10c286e size: 3462

IBM Cloud Container Registry 上にイメージがあることを確認します。

# ibmcloud cr images
イメージをリストしています...

リポジトリー                                       タグ   ダイジェスト   名前空間         作成日           サイズ   セキュリティー状況 
jp.icr.io/shimauma_zzzzz/default/liberty-counter   v3.0   a5d5a57c1570   shimauma_zzzzz   20 minutes ago   276 MB   1 件の問題

OK

セキュリティ状況に1件の問題が出ていますね。 
ここでは対応は割愛しますが、内容についてはコンソールで確認することが可能です。

63.png

64.png

2020/09/23) 追記
上記の脆弱性がやっぱり気になりましたので、対応しました。
こちらをご覧ください → 番外編.コンテナイメージのUpdate


お疲れ様でした。
今回はここまでとし、次回は [8.IKS へのコンテナのデプロイ] を実施します。

←:IKS + Db2 on IBM Cloud で DBアクセスアプリを動かしてみた(6.DBアクセスアプリケーションの準備 (java))
↑:IKS + Db2 on IBM Cloud で DBアクセスアプリを動かしてみた(1.概要)
→:IKS + Db2 on IBM Cloud で DBアクセスアプリを動かしてみた(8.IKS へのコンテナのデプロイ)


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

Go+MySQL+Dockerで簡単なCRUDを実装する

はじめに

先日、「業務で使う予定ないとはいえGoぐらいある程度知っておいたほうがいいよな...」と思い、Goを使って簡単なCRUDを実装してみたのでそのやり方を備忘録としてまとめておきます。

基本的には以下のサイトの内容を組み合わせて少しアレンジしたものになっています。Goの勉強をする上でこれらのサイトには非常にお世話になったのでこちらもご参考ください。
DockerでGoの開発環境を構築する
Go / Gin で超簡単なWebアプリを作る
Go言語(Golang)入門~MySQL接続編~
docker-compose MySQL8.0 のDBコンテナを作成する
docker-compose upでMySQLが起動するまで待つ方法(2種類紹介)

GoをDockerで立ち上げる

まずはGoをDockerで立ち上げていきます。
作業ディレクトリ直下に
- DockerFile
- docker-compose.yml
- main.go
を作成します

DockerFile
FROM golang:latest

RUN mkdir /app
WORKDIR /app
docker-compose.yml
version: '3'
services:
  go:
    build:
      context: .
      dockerfile: DockerFile
    command: /bin/sh -c "go run main.go"
    stdin_open: true
    tty: true
    volumes:
      - .:/app
main.go
package main

import "fmt"

func main() {
  fmt.Println("Hello, World!")
}

これでdocker-compose upを行うとコンソール上にHello, World!と出てくると思います。
これが出ればまずGoの起動は成功です。

簡単に各ファイルの解説をします。
・DockerFile
Goのコンテナ(仮想環境)を作成します。
ここでWORKDIR /appを指定していることで以降の動作をすべて/app以下で行ってくれます。

・docker-compose.yml
DockerFileで作ったコンテナを立ち上げるときの設定などを書きます。
これにより、DockerFileにあるコンテナを立ち上げてその中でgo run main.goのコマンドを叩いてmain.goを起動します

・main.go
Goに関する処理はここに書いていきます。今回はHello, World!を出力するだけで終了しています。

GoでWebページを作成する

とりあえずGoの起動ができたので次はGoを使ってWebページを作っていきましょう。
今回はGinというフレームワークを使ってみます。
- DockerFileにインストールを追加
- docker-compose.ymlにportsの記述を追加
- main.goの内容を書き換え
- templates/index.htmlを作成
を行ってください。

DockerFile
FROM golang:latest

RUN mkdir /app
WORKDIR /app

RUN go get github.com/gin-gonic/gin
docker-compose.yml
version: '3'
services:
  go:
    build:
      context: .
      dockerfile: DockerFile
    command: /bin/sh -c "go run main.go"
    stdin_open: true
    tty: true
    volumes:
      - .:/app
    ports:
      - 8080:8080
main.go
package main

import (
  "github.com/gin-gonic/gin"
)

func main() {
  router := gin.Default()
  router.LoadHTMLGlob("templates/*.html")

  router.GET("/", func(ctx *gin.Context){
    ctx.HTML(200, "index.html", gin.H{})
  })

  router.Run()
}
templates/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Sample App</title>
</head>
<body>
  <h1>Hello World!!!</h1>
</body>
</html>

これで

docker-compose build
docker-compose up -d

を行ってしばらく待ってから
http://localhost:8080にアクセスするとHello World!と表示されると思います。

今回やったことを解説します。
今回はGinというフレームワークを追加しました。
GinはDockerFileでコンテナ作成後にgo get github.com/gin-gonic/ginというコマンドでインストールされ、main.goで呼び出されます。
そしてmain.goの中でtemplatesの中身が読み取られ、

router.GET("/", func(ctx *gin.Context){
  ctx.HTML(200, "index.html", gin.H{})
})

によってroot("/")に対してtemplates/index.htmlが紐づけられることになります。
ちなみにrouter.GETの第一引数("/")を"/test"などに変えると、http://localhost:8080ではなく、http://localhost:8080/testでindex.htmlが表示されるようになります。

最後にdocker-compose.ymlにportを追加することでlocalhost:8080へのアクセスを可能にしています。

DockerでMySQLを起動する

ここまででGoでのWebページ作成はできるようになりました。しかし、実際にはWebサービスを作るときにDBとの接続は避けて通れない内容になってきます。
そこで次はDockerを使ってMySQLを立ち上げていきます。

まずはdocker-compose.ymlに
・dbコンテナについての記述
・volumeの記述
を追加してください。

docker-compose.yml
db:
  image: mysql:8.0
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_DATABASE: go_database
    MYSQL_USER: go_test
    MYSQL_PASSWORD: password
    TZ: 'Asia/Tokyo'
  command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
  volumes:
    - db-data:/var/lib/mysql
    - ./db/my.cnf:/etc/mysql/conf.d/my.cnf
  ports:
    - 3306:3306

volumes:
  db-data:
    driver: local

また、dbディレクトリを作り、その中にmy.cnfファイルを作成してください。

my.cnf
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_bin

default-time-zone = SYSTEM
log_timestamps = SYSTEM

default-authentication-plugin = mysql_native_password

[mysql]
default-character-set = utf8mb4

[client]
default-character-set = utf8mb4

(この辺は参考ページそのままです。ログに関する部分だけなぜか上手くいかなかったので外しています)

ここまでやってdocker-compose up -dをやるとMySQLのコンテナも立ち上がるはずです。
設定の記述しかないのでここの説明は省略します。

GoとMySQLを接続する

MySQLが立ち上がったので早速Goにつないでみます。
今回は接続にsqlドライバーとGORMというフレームワークを使います。
- DockerFileにインストールの追加
- docker-compose.ymlに依存関係の記述を追加
- main.goにDB接続の処理を追加
を行ってください。

DockerFile
FROM golang:latest

RUN mkdir /app
WORKDIR /app

RUN go get github.com/gin-gonic/gin
RUN go get github.com/go-sql-driver/mysql
RUN go get github.com/jinzhu/gorm
docker-compose.yml
version: '3'
services:
  go:
    build:
      context: .
      dockerfile: DockerFile
    command: /bin/sh -c "go run main.go"
    stdin_open: true
    tty: true
    volumes:
      - .:/app
    ports:
      - 8080:8080
    depends_on:
      - "db"

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: go_database
      MYSQL_USER: go_test
      MYSQL_PASSWORD: password
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - db-data:/var/lib/mysql
      - ./db/my.cnf:/etc/mysql/conf.d/my.cnf
    ports:
      - 3306:3306

volumes:
  db-data:
    driver: local
main.go
package main

import (
  "fmt"
  "time"

  "github.com/gin-gonic/gin"
  "github.com/jinzhu/gorm"
  _ "github.com/go-sql-driver/mysql"
)

func main() {
  db := sqlConnect()
  defer db.Close()

  router := gin.Default()
  router.LoadHTMLGlob("templates/*.html")

  router.GET("/", func(ctx *gin.Context){
    ctx.HTML(200, "index.html", gin.H{})
  })

  router.Run()
}

func sqlConnect() (database *gorm.DB) {
  DBMS := "mysql"
  USER := "go_test"
  PASS := "password"
  PROTOCOL := "tcp(db:3306)"
  DBNAME := "go_database"

  CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=true&loc=Asia%2FTokyo"

  count := 0
  db, err := gorm.Open(DBMS, CONNECT)
  if err != nil {
    for {
      if err == nil {
        fmt.Println("")
        break
      }
      fmt.Print(".")
      time.Sleep(time.Second)
      count++
      if count > 180 {
        fmt.Println("")
        fmt.Println("DB接続失敗")
        panic(err)
      }
      db, err = gorm.Open(DBMS, CONNECT)
    }
  }
  fmt.Println("DB接続成功")

  return db
}

これでdocker compose upを行い、コンソールに「DB接続成功」と出たら成功です。

追加された内容はsqlConnectがメインなのでそこを解説します。

func sqlConnect() (database *gorm.DB) {
  DBMS := "mysql"
  USER := "go_test"
  PASS := "password"
  PROTOCOL := "tcp(db:3306)"
  DBNAME := "go_database"

  CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=true&loc=Asia%2FTokyo"

  count := 0
  db, err := gorm.Open(DBMS, CONNECT)
  if err != nil {
    for {
      if err == nil {
        fmt.Println("")
        break
      }
      fmt.Print(".")
      time.Sleep(time.Second)
      count++
      if count > 180 {
        fmt.Println("")
        fmt.Println("DB接続失敗")
        panic(err)
      }
      db, err = gorm.Open(DBMS, CONNECT)
    }
  }
  fmt.Println("DB接続成功")

  return db
}

前半部はDBに接続するための情報を定義しています。docker-compose.ymlで設定した内容を入力してください。
その後、db, err := gorm.Open(DBMS, CONNECT)でDBに接続します。しかし、MySQLの起動時間によってはこのコマンドが実行される時点でMySQLの準備が完了していない場合があります。
そこでこのコードでは2つの対策をしています。

1つめはdocker-compose.ymlでの依存関係の設定です。
ここでdepends_onを設定したことにより、dbコンテナが立ち上がってからgoコンテナが立ち上がるようになります。

2つめはリトライ処理です。
dbコンテナが起動してからもMySQLが立ち上がるまでに時間がかかるのでもしDBにつながらなかった場合に1秒待ってからリトライするようにしています。
これだと本当にエラーのときにリトライし続けてしまうので適当な回数でエラーを返すようにします。このコードでは3分つながらなかったらエラーになるようになっています。

CRUDを実装する

ついにMySQLにもつながるようになったので最後にCRUDの処理を実装して実際の流れをみていきましょう。
あと変更するのはmain.goとindex.htmlのみです。
- Userの定義を作成
- マイグレーション
- post処理の実装
- ユーザー追加フォーム、ユーザー削除ボタンの実装
をやっていきます。

main.go
package main

import (
  "fmt"
  "strconv"
  "time"

  "github.com/gin-gonic/gin"
  "github.com/jinzhu/gorm"
  _ "github.com/go-sql-driver/mysql"
)

type User struct {
  gorm.Model
  Name string
  Email string
}

func main() {
  db := sqlConnect()
  db.AutoMigrate(&User{})
  defer db.Close()

  router := gin.Default()
  router.LoadHTMLGlob("templates/*.html")

  router.GET("/", func(ctx *gin.Context){
    db := sqlConnect()
    var users []User
    db.Order("created_at asc").Find(&users)
    defer db.Close()

    ctx.HTML(200, "index.html", gin.H{
      "users": users,
    })
  })

  router.POST("/new", func(ctx *gin.Context) {
    db := sqlConnect()
    name := ctx.PostForm("name")
    email := ctx.PostForm("email")
    fmt.Println("create user " + name + " with email " + email)
    db.Create(&User{Name: name, Email: email})
    defer db.Close()

    ctx.Redirect(302, "/")
  })

  router.POST("/delete/:id", func(ctx *gin.Context) {
    db := sqlConnect()
    n := ctx.Param("id")
    id, err := strconv.Atoi(n)
    if err != nil {
      panic("id is not a number")
    }
    var user User
    db.First(&user, id)
    db.Delete(&user)
    defer db.Close()

    ctx.Redirect(302, "/")
  })

  router.Run()
}

func sqlConnect() (database *gorm.DB) {
  DBMS := "mysql"
  USER := "go_test"
  PASS := "password"
  PROTOCOL := "tcp(db:3306)"
  DBNAME := "go_database"

  CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=true&loc=Asia%2FTokyo"

  count := 0
  db, err := gorm.Open(DBMS, CONNECT)
  if err != nil {
    for {
      if err == nil {
        fmt.Println("")
        break
      }
      fmt.Print(".")
      time.Sleep(time.Second)
      count++
      if count > 180 {
        fmt.Println("")
        panic(err)
      }
      db, err = gorm.Open(DBMS, CONNECT)
    }
  }

  return db
}
templates/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Sample App</title>
</head>
<body>
  <h2>ユーザー追加</h2>
  <form method="post" action="/new">
    <p>名前<input type="text" name="name" size="30" placeholder="入力してください" ></p>
    <p>メールアドレス<input type="text" name="email" size="30" placeholder="入力してください" ></p>
    <p><input type="submit" value="Send"></p>
  </form>

  <h2>ユーザー一覧</h2>
  <table>
    <tr>
      <td>名前</td>
      <td>メールアドレス</td>
    </tr>
    {{ range .users }}
      <tr>
        <td>{{ .Name }}</td>
        <td>{{ .Email }}</td>
        <td>
          <form method="post" action="/delete/{{.ID}}">
            <button type="submit">削除</button>
          </form>
        </td>
      </tr>
    {{ end }}
  </ul>
  </body>
</html>

これでdocker-compose up -dを行い、http://localhost:8080にアクセスするとユーザー登録フォームが現れ、ユーザーを登録すると下に登録したユーザーの情報が表示されるようになります。
また、コンテナを削除して上げ直しても登録されたユーザーは削除されず、ユーザー一覧に表示が残るようになります。

それでは追加部分の解説をしていきます。
まず、main.goでUserという構造体を作成しています。gorm.Modelでidなどモデルに必要な内容をUserに入れ、更にUser特有のname, emailを追加しています。
この構造はdb.AutoMigrateによってDBに反映されます。

続いて各パスでのCRUD処理を実装していきます。

rootパスではユーザー一覧を取得します。
db.Find(&users)でDB内にあるユーザー一覧をUser構造として取得します。
間にOrderを挟むことで取得時に古いユーザーが上に来るようにしています。
最後に取得したユーザーをindex.htmlに渡しています。

/newパスではフォームの内容をもとにユーザーを作成しています。
ctx.PostFormでフォームによってsubmitされた内容を取得し、その内容をdb.Createで永続化しています。
処理が終わったらrootにリダイレクトします。

/deleteパスではidを指定してユーザーを削除しています。
こちらではURLにユーザーのidを指定しているのですが、同様にctxから取得します。
そしてその内容からdb.Firstでユーザーを取得し、db.Deleteで該当のユーザーを削除します。
ここで、idはstringで渡されているのでstrconv.Atoiでint型に変換していることに注意してください。

index.htmlでは一般的なhtmlの書き方でformとtableを作成しています。
ここで、{{ range .users }}という形でmain.goから渡されたusersを受け取っています。

おわりに

今回はGoでのWebサービス開発の導入としてGo+MySQL+Dockerで簡単なCRUDを実装してみました。あくまで練習なのでバリデーションとか細かい制御などは考えていません。
今回行った内容は初歩ではありますが、この内容を広げて複雑化していくことで実際にWebサービスを作ることができると思います。
もしGoで何か作ってみたいと考えている方がいらっしゃったらぜひ参考にしてみてください!

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

【SRE/Docker】Dockerizeでの起動制御

docker-composeを使用する際にDBの接続を待ちたいなどがあった時に便利な Dockerize について書いていきます。

起動制御の選択肢

下記をみる限り、wait-for-itdockerize の2つが有効なようです。
Compose における起動順の制御 — Docker-docs-ja 17.06 ドキュメント

Docker Compose でMySQLが起動するまで待つ - Qiita
docker-compose upでMySQLが起動するまで待つ方法(2種類紹介) - Qiita

Dockerize

Dockerizeとは

GitHub - jwilder/dockerize: Utility to simplify running applications in docker containers

使う

dockerfiledocker-compose.yaml を修正します。

ENV DOCKERIZE_VERSION v0.6.0
RUN apk add --no-cache openssl \
    && wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz

dockerize のコマンドを docker-composeで定義します。
dockerize -wait tcp://db:5432 というコマンドで、依存関係のあるアプリケーションの起動を待つことができるようになります。

entrypoint:
  - dockerize
  - -timeout
  - 60s
  - -wait
  - tcp://mysql:3306
command: ./main # goでの実行

Dockerizeを使って他のコンテナの起動を待つ - Qiita

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

Windows10 HomeでもDockerの環境構築できる !! WSL1 からWSL2に変更する際に出るエラー error : 0x800701bc の解決方

Docker 初学者必見!!

2020-09-22 (7).png

はじめに

・Windows10 ユーザー

・Dockerの環境構築をしたい

・WSL2の設定に困っている

人に向けた、記事になります。

公式サイト

? https://docs.microsoft.com/ja-jp/windows/wsl/install-win10#enable-the-virtual-machine-platform-optional-component

2020-09-22 (4).png

これにそって進めます。
(※ページの下の方にはいくつかのトラブルシューティングが記載されています。)

Windows10 Home のバージョンを確認してください!

2020-09-22 (3).png

error : 0x800701bc の解決方!

2020-09-22.png

同じようなエラーが出た人は、Linux kernelのupdateをしなければ、Linuxが起動しません。

そこで、GitHubで解決方を探していたところ、海外:flag_us:の方が解決していたのでその記事を掲載します。

参考にしたGitHubのページ

( https://github.com/microsoft/WSL/issues/5393 )
2020-09-22 (5).png

:star:要は、kernelのupdateが必要:star:

こちらのサイトから、updateができます!!
https://docs.microsoft.com/en-us/windows/wsl/install-win10#step-4---download-the-linux-kernel-update-package

2020-09-22 (6)_LI.jpg

インストーラ起動させれば、解決!

これで、Linuxを起動させることができます??????

あとは、Dockerのインストーラを起動して、順に進めれば完了です:star:

Dockerの学習に役立てばうれしいです:blush:

引用

GitHub ➡ https://github.com/microsoft/WSL/issues/5393

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

Windows10 HomeでもDockerの環境構築ができる !! WSL1 からWSL2に変更する際に出るエラー error : 0x800701bc の解決方! (2020年9月)

Docker 初学者必見!!

2020-09-22 (7).png

はじめに

・Windows10 ユーザー

・Dockerの環境構築をしたい

・WSL2の設定に困っている

人に向けた、記事になります。

公式サイト

? https://docs.microsoft.com/ja-jp/windows/wsl/install-win10#enable-the-virtual-machine-platform-optional-component

2020-09-22 (4).png

これにそって進めます。
(※ページの下の方にはいくつかのトラブルシューティングが記載されています。)

Windows10 Home のバージョンを確認してください!

2020-09-22 (3).png

error : 0x800701bc の解決方!

2020-09-22.png

同じようなエラーが出た人は、Linux kernelのupdateをしなければ、Linuxが起動しません。

そこで、GitHubで解決方を探していたところ、海外:flag_us:の方が解決していたのでその記事を掲載します。

参考にしたGitHubのページ

( https://github.com/microsoft/WSL/issues/5393 )
2020-09-22 (5).png

:star:要は、kernelのupdateが必要:star:

こちらのサイトから、updateができます!!
https://docs.microsoft.com/en-us/windows/wsl/install-win10#step-4---download-the-linux-kernel-update-package

2020-09-22 (6)_LI.jpg

インストーラを起動させれば、解決!

これで、Linuxを起動させることができます??????

あとは、Dockerのインストーラを起動して、順に進めれば完了です:star:

Dockerの学習に役立てばうれしいです:blush:

引用

GitHub ➡ https://github.com/microsoft/WSL/issues/5393

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