- 投稿日:2020-06-28T23:49:07+09:00
VirtualBoxとDockerでお勉強用の環境を作ってみた
VirtualBoxとDockerでお勉強用の環境を作ってみた
- 気になるソフトウェアを動かして、挙動を見てみたい。
- ソフトウェアの設定を変えていろいろ実験したい
- 複数のサーバーをつかうつもりでやってみたい
- 失敗時に自力で環境を戻す自信がない(戻すのがめんどくさい)ので、環境の再作成を頻繁にしたい
など思ったときに使っている、お試し環境の構築手順です。主に自宅などでのお勉強での使用を想定しています。
仮想マシンをVirtualBoxで作成し、そこにDockerをインストールします。
Dockerを使うと、プロセスを隔離環境(コンテナ)で実行できます。仮想マシンと違い、コンテナは気軽に作成/削除できるため、失敗を気にせずに気軽にいろいろ実験するにはもってこいです。
環境
種別 OS 備考 ホスト(物理マシン) Windows 10 Home 1909 インターネットへ接続可能 ゲスト(仮想マシン) CentOS Linux release 7.8.2003 - 目次
- 1. 仮想マシンの構築
- 1.1 VirtualBoxのインストール
- 1.2 CentOS7イメージのダウンロード
- 1.3 仮想マシンの作成
- 1.4 ネットワーク接続設定
- 1.5 CentOS7インストール
- 1.6 インターネット接続の確認
- 2. CentOS 7初期設定
- 2.1 カーネル最新化
- 2.2 パッケージの更新など
- 2.3 ホスト-ゲスト共有フォルダの有効化
- 2.4 一般ユーザーの作成
- 2.5 SSH設定
- 2.6 mDNS設定
- 3. Visual Studio Codeの導入
- 4. 開発環境の構築
- 4.1 Gitの最新化
- 4.2 Dockerのインストール
- 4.3 Python3のインストール
- 4.4 docker-composeのインストール
- 4.5 Visual Studio Code拡張機能インストール
- 5. デモ
- 5.1 最低限のWebサイトを構築してみる
- 5.2 Apache Web Server + Tomcatで最小Webアプリを作ってみる
- 6. まとめ
1. 仮想マシンの構築
1.1 VirtualBoxのインストール
VirtualBoxは仮想化ソフトウェアです。Windows用のインストーラーをダウンロードしてインストールします。インストール先はどこでもよいですが、ここでは
C:\App\VirtualBox
にインストールします。1.2 CentOS7イメージのダウンロード
CentOS 7のDVDイメージを以下のURLからダウンロードします。時間がかかるので、気長に待ちます。
https://www.centos.org/download/
※ CentOS 8が既にリリースされていますが、まだDockerが公式にサポートしていません。
1.3 仮想マシンの作成
VirtualBoxマネージャーを開きます。
新規
をクリックします。仮想マシンの名前と保存先を指定します。今回は以下のように設定します。
メモリは2.0GBとします。必要に応じて変えてください。
仮想ハードディスクを固定サイズ32GBで作成します。Dockerイメージ分の容量を確保するため、このくらいにしておきます。
以上で仮想マシンの作成が終わりました。
1.4 ネットワーク接続設定
仮想マシンがホストのネットワークにブリッジ接続するようにします。ホストからインターネット接続できるのであれば、仮想マシンからもインターネット接続できるようになると思います。
1.5 CentOS 7インストール
先ほどダウンロードしたCentOS 7のイメージを仮想マシンの光学ドライブにセットします。
仮想マシンを起動してCentOS 7をインストールします。ネットワークの接続はインストール時にオンにしておきます。
1.6 インターネット接続の確認
rootユーザーで仮想マシンにログイン後、適当なインターネット上のWebサイトにアクセスできることを確認します。
# curl --head https://www.google.com/ HTTP/1.1 200 OK Date: Sat, 14 Mar 2020 16:32:34 GMT ...2. CentOS 7初期設定
不安であれば、作業前に仮想マシンのスナップショットを取っておくとよいです。
2.1 カーネル最新化
なんとなくカーネルを最新化してみます。以下を参考に実施していきます。
今回のカーネルのバージョンは以下です。
- デフォルト:3.10.0
- 最新:5.7.6
まずはELRepoを有効化します。
# yum install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpmkernel-mlをインストールします。
# yum --enablerepo=elrepo-kernel install kernel-ml# yum list installed kernel* 読み込んだプラグイン:fastestmirror Loading mirror speeds from cached hostfile * base: ftp.riken.jp * elrepo: ftp.yz.yamagata-u.ac.jp * extras: ftp.riken.jp * updates: ftp.riken.jp インストール済みパッケージ kernel.x86_64 3.10.0-1127.el7 @anaconda kernel-ml.x86_64 5.7.6-1.el7.elrepo @elrepo-kernel kernel-tools.x86_64 3.10.0-1127.el7 @anaconda kernel-tools-libs.x86_64 3.10.0-1127.el7 @anaconda再起動後、新しいカーネル(5.7.6)で起動します。再起動後に以下のコマンドでカーネルのバージョンが最新版になっていることを確認します。
# uname --kernel-release 5.7.6-1.el7.elrepo.x86_64残りの最新版カーネルパッケージをインストールします。
yum swap
を使って、古いカーネルパッケージの削除と新しいカーネルパッケージのインストールを同時に行います。# yum --enablerepo=elrepo-kernel \ swap \ -- install kernel-ml-* \ -- remove kernel kernel-tools kernel-tools-libs※
yum swap
を使わずにそのままインストールしようとすると、古いものと依存関係が競合して失敗します。エラー: kernel-ml-tools conflicts with kernel-tools-3.10.0-1127.13.1.el7.x86_64 エラー: kernel-ml-tools-libs conflicts with kernel-tools-libs-3.10.0-1127.13.1.el7.x86_64これで新しいカーネルのインストールが完了しました。以下で確認します。
# yum list installed kernel* 読み込んだプラグイン:fastestmirror Loading mirror speeds from cached hostfile * base: ftp.riken.jp * elrepo: ftp.yz.yamagata-u.ac.jp * extras: ftp.riken.jp * updates: ftp.riken.jp インストール済みパッケージ kernel-ml.x86_64 5.7.6-1.el7.elrepo @elrepo-kernel kernel-ml-devel.x86_64 5.7.6-1.el7.elrepo @elrepo-kernel kernel-ml-doc.noarch 5.7.6-1.el7.elrepo @elrepo-kernel kernel-ml-headers.x86_64 5.7.6-1.el7.elrepo @elrepo-kernel kernel-ml-tools.x86_64 5.7.6-1.el7.elrepo @elrepo-kernel kernel-ml-tools-libs.x86_64 5.7.6-1.el7.elrepo @elrepo-kernel kernel-ml-tools-libs-devel.x86_64 5.7.6-1.el7.elrepo @elrepo-kernel2.2 パッケージの更新など
以下を実行して、CentOS 7のパッケージを最新化します。
# yum update後で使うのでnet-toolsをインストールします。netstatコマンドが使えるようになります。
# yum install net-tools終わったら、一度ゲストを再起動しておきます。
2.3 ホスト-ゲスト共有フォルダの有効化
ホスト-ゲストの間でフォルダの共有を行うことで、ファイルのやり取りを簡単にします。以下の情報を参考に実施します。
ゲストにVirtualBox - Guest Additionsのインストールが必要です。
まずは必要なパッケージをインストールします。
# yum groupinstall "development tools"次に、Guest Additionsのディスクイメージを挿入します。ディスクイメージはWindowsホストであれば、VirtualBoxのインストールディレクトリにあります。
以下のようにマウントします。
# mkdir /media/cdrom # mount /dev/cdrom /media/cdrom mount: /dev/sr0 is write-protected, mounting read-only# ls -l /media/cdrom 合計 45705 -r--r--r--. 1 root root 763 2月 20 22:27 AUTORUN.INF dr-xr-xr-x. 2 root root 1824 5月 15 03:49 NT3x dr-xr-xr-x. 2 root root 2652 5月 15 03:49 OS2 -r--r--r--. 1 root root 547 5月 15 03:49 TRANS.TBL -r--r--r--. 1 root root 3755310 5月 15 03:41 VBoxDarwinAdditions.pkg -r-xr-xr-x. 1 root root 3949 5月 15 03:41 VBoxDarwinAdditionsUninstall.tool -r-xr-xr-x. 1 root root 6737330 5月 15 03:42 VBoxLinuxAdditions.run -r--r--r--. 1 root root 9317888 5月 15 04:43 VBoxSolarisAdditions.pkg -r-xr-xr-x. 1 root root 16832808 5月 15 03:46 VBoxWindowsAdditions-amd64.exe-r-xr-x r-x. 1 root root 9863040 5月 15 03:45 VBoxWindowsAdditions-x86.exe -r-xr-xr-x. 1 root root 270616 5月 15 03:43 VBoxWindowsAdditions.exe -r-xr-xr-x. 1 root root 6384 5月 15 03:42 autorun.sh dr-xr-xr-x. 2 root root 792 5月 15 03:49 cert -r-xr-xr-x. 1 root root 4821 5月 15 03:42 runasroot.shGuest Additionsをインストールします。以下のコマンドを実行します。
# cd /media/cdrom # sh ./VBoxLinuxAdditions.run共有フォルダを設定するために、一度仮想マシンをシャットダウンします。終わったら仮想マシンの設定画面から共有フォルダの設定を開き、以下のように設定します。パスはお好みで設定してください。
- ホスト(Windows)のフォルダ:
C:\shared\centos7_sandbox
- ゲスト(CentOS 7)のマウント先ディレクトリ:
/mnt/host
これで指定したフォルダをホスト-ゲスト間で共有することができるようになりました。
2.4 一般ユーザーの設定
常にrootユーザーで作業するのは好ましくないです。root権限が不要の場面では一般ユーザーを使います。
ユーザーを作成します。名前はすきにつけましょう。ここではrolengraysとします。パスワードも設定しましょう。
# useradd --user-group rolengrays # passwd rolengrays2.3節で設定した共有フォルダにアクセスするためには、
vboxsf
グループに入る必要があります。# usermod -aG vboxsf rolengraysrolengraysユーザーでsudoできるようにします。sudoersファイルの文法エラーを防ぐため、visudoコマンドから編集します。
# visudo -f /etc/sudoers.d/rolengraysファイルの内容は以下の一行のみとします。
/etc/sudoers.d/rolengraysrolengrays ALL = (ALL) ALL2.5 SSH接続設定
2.4節で作成したユーザーでホストからSSH接続できるようにします。3節で使います。
ホストで、SSH用鍵を作成します。最近のWindows10にはデフォルトでSSHクライアント(OpenSSH)がインストールされています。
(ホストで実行) C:\> ssh-keygen -t rsa -b 2048 -N "" -f %USERPROFILE%\.ssh\rolengrays.keyホストで、公開鍵のほうを共有フォルダにコピーします。
(ホストで実行) c:\> copy %USERPROFILE%\.ssh\rolengrays.key.pub C:\shared\centos7_sandbox 1 個のファイルをコピーしました。ゲストで、公開鍵認証の有効化するため、
/etc/ssh/sshd_config
を編集してPubkeyAuthentication yes
のコメントアウトを外します。(ゲストで実行) ... - # PubkeyAuthentication yes + PubkeyAuthentication yes ...終わったらsshdを再起動して設定を反映します。
(ゲストで実行) # systemctl restart sshd以下のようにrolengraysユーザーの公開鍵を登録します。パーミッションは正しく設定しないとSSH接続が失敗します。
(ゲストで実行) # su - rolengrays $ mkdir --mode 700 ${HOME}/.ssh $ cat /mnt/host/rolengrays.key.pub >> ${HOME}/.ssh/authorized_keys $ chmod 600 ${HOME}/.ssh/authorized_keys後で使うので、ゲストのIPアドレスを調べておきます。
(ゲストで実行) $ ip addressホストの
%USERPROFILE%\.ssh\config
にSSH設定ファイルを作成します。調べたIPアドレスをHostNameに指定します。%USERPROFILE%\.ssh\configHost centos7_sandbox HostName 192.168.43.119 User rolengrays IdentityFile "~/.ssh/rolengrays.key"ホストからSSH接続してみます。SSH経由でコマンドを正しく実行できることを確認します。
(ホストで実行) c:\>ssh centos7_sandbox cat /etc/redhat-release CentOS Linux release 7.8.2003 (Core)2.6 mDNS設定
2.5節の手順で仕組み上はSSH接続ができるようになりました。しかし、DHCPで各ホストにIPアドレスを動的に割りあてている場合、ゲストのIPアドレスが意図せず変更されることがあります。そうなるとまたゲストのIPアドレスを調べおして、
%USERPROFILE%\.ssh\config
を更新する必要があります。これでは面倒なので、mDNSの仕組みを使って同じネットワーク内のIPアドレスをホスト名で解決できるようにします。※ Windows 10のバージョンが古いと、mDNSクライアントがデフォルトで入っていない場合があります。
まずはゲストにホスト名を設定します。自分の好きな名前を付けましょう。ここでは
c7sandbox
とします。終わったら、ゲストを再起動しておきます。(ゲストで実行) # hostnamectl set-hostname c7sandbox続いて、ゲストにmDNSデーモンをインストールします。
(ゲストで実行) # yum install avahiavahi-daemonサービスを起動します。自動起動もONにしておきます。
(ゲストで実行) # systemctl enable avahi-daemon # systemctl start avahi-daemon5353/UDPがLISTENしていることを確認します。
(ゲストで実行) # netstat -nulp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 0.0.0.0:40913 0.0.0.0:* 1464/avahi-daemon: udp 0 0 0.0.0.0:68 0.0.0.0:* 865/dhclient udp 0 0 0.0.0.0:5353 0.0.0.0:* 1464/avahi-daemon: udp 0 0 127.0.0.1:323 0.0.0.0:* 718/chronyd udp6 0 0 ::1:323 :::* 718/chronyd最後にfirewalldの設定を変更し、外から5353/UDPへの通信を許可するようにします。デフォルトゾーンをhomeにします。
(ゲストで実行) # firewall-cmd --set-default-zone=home successhomeゾーンが、現在使っているインターフェースに設定されていることを確認します。
(ゲストで実行) # firewall-cmd --get-active-zones home interfaces: enp0s3※ homeゾーンではmdnsサービスがデフォルトで有効に設定されています。以下のコマンドで確認します。
(ゲストで実行) # firewall-cmd --zone home --list-services dhcpv6-client mdns samba-client ssh※ mdnsサービスは5353/UDPを許可しています。
(ゲストで実行) # firewall-cmd --service mdns --get-ports --permanent 5353/udpfirewalldを再起動して設定を反映します。
(ゲストで実行) # systemctl restart firewalldホストの、
%USERPROFILE%\.ssh\config
ファイルを書き換えます。ゲストのホスト名がc7sandbox
なので、末尾に.local
をつけたものをHostNameに指定します。※ mDNSはデフォルトで、"ホスト名 + .local"で名前解決するためです。
%USERPROFILE%\.ssh\configHost centos7_sandbox HostName c7sandbox.local User rolengrays IdentityFile "~/.ssh/rolengrays.key"ホストからもう一度SSHできることを確認します。
(ホストで実行) c:\>ssh centos7_sandbox hostname c7sandboxこれでIPアドレスではなく、名前でホストからゲストにSSH接続ができました。
3. Visual Studio Codeの導入
Visual Studio Codeをインストールします。このテキストエディタには豊富な拡張機能があり、開発を強力にサポートしてくれます。
Remote Development拡張機能をインストールします。これを使うと、ゲストのファイルをホストで簡単に編集できます。
2.4節、2.5節のSSH設定ファイルをこの拡張機能が認識しているので、すぐにSSH接続できます。
4. 開発環境の構築
不安な場合は仮想マシンのスナップショットを取っておくとよいです。
4.1 Gitの最新化
開発環境ではバージョン管理システムが必要となる場面が多いです。Gitを使うことにします。ここまでの作業を実施している場合、既にGitがインストールされていますが、バージョンが古いので最新化します。(4.5節で導入するVisual Studio CodeのGit拡張機能がGitのバージョン2.0以上でうまく動作するため。)
現在のGitのバージョン(CentoOS 7デフォルト)は以下です。
# git --version git version 1.8.3.1執筆時点の最新版は
2.27.0
です。手順は以下を参考にします。ビルド前の準備します。Gitのビルドに必要な以下のパッケージをインストールします。
# yum install \ zlib-devel \ perl-devel \ openssl-devel \ curl-devel \ expat-devel \ gettext-develドキュメントのビルドに必要な以下のパッケージをインストールします。(ドキュメントはいらないかもしれませんが...)
# yum install \ asciidoc \ xmlto既にある古いGitでGitそのもののリポジトリをcloneしてきます。
# cd /tmp # git clone https://github.com/git/git.git最新版をチェックアウトします。
# cd /tmp/git # git checkout v2.27.0ビルド/インストールします。インストール先は
/usr/local
にします。少し時間がかかるので気長に待ちましょう。# make configure # ./configure --prefix=/usr/local # make all doc # make install install-doc install-htmlhashをリセットしたあと、新しいGitのバージョンを確認します。
# hash -r # git --version git version 2.27.04.2 Dockerのインストール
Docker Engineをインストールします。Dockerによって、プロセスを隔離した環境で実行できます。以下を参考にします。
必要なパッケージをインストールします。
# yum install \ yum-utils \ device-mapper-persistent-data \ lvm2リポジトリを有効化します。
# yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repoインストールします。
# yum install \ docker-ce \ docker-ce-cli \ containerd.iodockerサービスの自動起動を有効化、起動します。
# systemctl enable docker # systemctl start docker動作確認します。
# docker run hello-world4.2.1 dockerグループへの追加
rolengraysユーザーをdockerグループに追加します。これでsudoなしでrolengraysユーザーがdockerコマンドを実行できます。
# usermod -aG docker rolengrays※ ユーザーdockerグループに追加すると、Dockerホストでそのユーザーにroot権限を与えることとほぼ同じとなります。
4.3 Python3のインストール
Python3をインストールします。あとでインストールするdocker-composeの
1.25.x
以降のバージョンがPython2をサポートしないためです。(そしてPython2は既に公式のサポートが切れています。)CentOS 7はデフォルトだとPython2しかインストールされていません。以下を参考にインストールします。
必要なパッケージをインストールします。
# yum groupinstall "development tools" # yum install \ bzip2-devel \ gdbm-devel \ libffi-devel \ libuuid-devel \ ncurses-devel \ openssl-devel \ readline-devel \ sqlite-devel \ tk-devel \ wget \ xz-devel \ zlib-develソースコードをダウンロードします。
# cd /tmp # wget https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz # tar -xzf Python-3.8.3.tgzビルド・インストールします。
# cd /tmp/Python-3.8.3 # ./configure --enable-shared # make # make install # sh -c "echo '/usr/local/lib' > /etc/ld.so.conf.d/custom_python3.conf" # ldconfigバージョンを確認します。
# python3 --version Python 3.8.34.4 docker-composeのインストール
docker-composeは同時に複数のコンテナを使うアプリケーションを定義・実行できるツールです。コンテナの実行はdockerコマンドでも実施できますが、オプションが長いコマンドを複数回打つのは非常に面倒です。docker-composeはこの問題を解決できます。以下の通りインストールします。
執筆時点の最新版は
1.26.0
です。# curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # chmod +x /usr/local/bin/docker-compose# docker-compose --version docker-compose version 1.26.0, build d44516594.5 Visual Studio Code拡張機能のインストール
以下の拡張機能をインストールしておきます。細かい機能は紹介しませんが、便利です。実際にインストールして機能を確かめてみてください。
- GitLens(行ごとのBlameができる、ファイルの編集履歴をGUIで確認できる、など)
- Docker(実行中のコンテナや手元にあるイメージなどをGUIで表示してくれる、など)
ここまでで、環境構築は終わました。
5. デモ
利用例を紹介します。
5.1 最低限のWebサイトを構築してみる
最低限のWebサイトをDockerコンテナで構築してみます。最終的にカレントディレクトリ配下は以下のようになります。
. ├── c7-base │ └── Dockerfile ├── c7-systemd │ └── Dockerfile └── docker-compose.yml5.1.1 systemd有効コンテナイメージの作成
systemdを有効にしたコンテナの定義を作成します。
./c7-systemd/Dockerfile
を以下のようにします。centos - Docker HubからDockerfileを引用します。./c7-systemd/Dockerfile# https://hub.docker.com/_/centos より引用 FROM centos:7 ENV container docker RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \ systemd-tmpfiles-setup.service ] || rm -f $i; done); \ rm -f /lib/systemd/system/multi-user.target.wants/*;\ rm -f /etc/systemd/system/*.wants/*;\ rm -f /lib/systemd/system/local-fs.target.wants/*; \ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ rm -f /lib/systemd/system/basic.target.wants/*;\ rm -f /lib/systemd/system/anaconda.target.wants/*; VOLUME [ "/sys/fs/cgroup" ] CMD ["/usr/sbin/init"]c7-systemdのコンテナイメージをビルドします。
$ docker build -t local/c7-systemd ./c7-systemd5.1.2 自分の基本イメージの作成
基本イメージを作成します。目的にかかわらず、自分がよく使う汎用パッケージや設定などをあらかじめコンテナイメージにしておくと便利です。
./c7-base/Dockerfile
を以下のようにします。先ほどビルドしたlocal/c7-systemd
をベースにした上で、よく使うパッケージを自分で適当に選んでインストールするとよいです。デフォルトだとタイムゾーンがUTCなので、JSTに設定しておきます。./c7-base/DockerfileFROM local/c7-systemd # アップデート&パッケージインストール RUN yum update -y \ && yum install -y \ wget \ tree \ which \ net-tools # タイムゾーン設定 RUN /usr/bin/ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtimeこちらもビルドします。
$ docker build -t local/c7-base ./c7-base5.1.3 docker-compose.ymlの作成
docker-compose.ymlを作成します。通常、Dockerコンテナを実行するためには、場合によっては長いコマンドラインオプションを複数打たなければならず、面倒です。
./docker-compose.yml
を以下のようにします。コンテナ1つだけ定義します。./docker-compose.yml--- version: "3.7" services: c7-base: build: context: ./c7-base image: local/c7-base container_name: c7-base working_dir: /root privileged: true # systemdをコンテナ内で使用するための設定 stdin_open: true tty: true # Dockerホストの'8080/TCP'をコンテナの'80/TCP'にマッピングするため ports: - published: 8080 target: 80 protocol: tcp mode: host volumes: # systemdをコンテナ内で使用するための設定 - type: bind source: /sys/fs/cgroup target: /sys/fs/cgroup read_only: true※ 上記のdocker-compose定義でのコンテナ実行は、以下のコマンドとほぼ同等です。
# docker run -it --privileged -w /root -p 8080:80 -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name c7-base local/c7-base5.1.4 コンテナ内でのWebサーバーの作成作業
docker-composeでdockerコンテナを起動します。
$ docker-compose -f ./docker-compose.yml up -ddockerコンテナにシェルをアタッチします。Visual Studio CodeのDocker拡張機能を使えば、コマンドなしでできます(コンテナを右クリック->Attach Shell)。
[rolengrays@c7sandbox ~]$ docker exec -it c7-base /bin/bash [root@0b7b64ad6eb6 ~]#これでコンテナ内でコマンドを実行できるようになりました。試しにhttpdをインストールして、コンテナ内にWebサーバーを作ってみます。内容が"Hello From Container"のみの簡単なHTMLドキュメントも用意しておきます。
(コンテナ内で実行) # yum install httpd # echo "Hello From Container" > /var/www/html/index.html # systemctl start httpd終わったら
exit
コマンドで抜けます。5.1.5 コンテナ内のWebサーバーにアクセス
ホストからこのWebサーバーにアクセスしてみます。ゲストの'8080/TCP'をコンテナの'80/TCP'にマッピングするように設定しているため、firewalldに8080/TCPを許可する設定をする必要があります。
まずはサービスを作成します。名前は
http_8080
とします。以下のようなXMLファイルを作成すればOKです。/usr/lib/firewalld/services/http_8080.xml<?xml version="1.0" encoding="utf-8"?> <service> <short>HTTP(8080)</short> <description>HTTP 8080 Port</description> <port protocol="tcp" port="8080"/> </service>ファイルを作成したら、リロードします。
(ゲストで実行) # firewall-cmd --reload次にhomeゾーンに先ほど作成した
http_8080
を追加します。追加したら、もう一度リロードします。(ゲストで実行) # firewall-cmd --permanent --zone home --add-service http_8080 # firewall-cmd --reloadこれで8080/TCPに外からアクセスできるようになりました。ホストでWebブラウザを立ち上げて、
http://c7sandbox.local:8080/index.html
にアクセスしてみましょう。Hello From Container
が表示されれば成功です。Webサーバーのインストールを最初からやり直したい場合は、以下のように一度downしてから、再度upすることで環境(コンテナ)を再構築できます。
$ docker-compose down $ docker-compose up -dこれでインストールからやり直すことができます。今回はhttpdをインストールするだけの例ですが、代わりにnginxをインストールしてみたりと、ほかにもいろいろな実験を行うことができます。もう一度シェルをアタッチしてアクセスログを見たりもできます。
5.2 Apache Web Server + Tomcatでデモ用Webアプリを作ってみる
複数のコンテナを使用するパターンで試してみます。Apache Web ServerのコンテナとTomcatのコンテナを作成し、それらを連携させてみます。プロジェクトのディレクトリ構成は最終的に以下のようになります。
demo52 ├── app │ ├── Dockerfile │ ├── build.sh │ ├── conf │ │ └── server.xml │ ├── resource │ │ ├── apache-tomcat-9.0.36.tar.gz │ │ └── openjdk-14.0.1_linux-x64_bin.tar.gz │ └── testapp │ ├── pom.xml │ (略) ├── docker-compose.yml └── proxy ├── Dockerfile └── conf └── app.conf以下に簡単なイメージを載せておきます。
5.2.1 テスト用Webアプリの作成
Tomcatの上で動かす簡単なアプリを作ります。ビルドツールはMavenを使います。公式のDockerイメージを使いましょう。
まずはDockerホスト側にMavenローカルリポジトリを作成します。これをコンテナ内に置いてしまうと、コマンド実行後にダウンロードしたパッケージがコンテナごと破棄されてしまいます。こうなると2度目のビルド以降も大量のダウンロードが発生するため、時間の無駄になります。コンテナ実行後も永続化したいファイルはコンテナ外(ここではDockerホスト)に配備するのがよいです。
$ mkdir -p ${HOME}/data/maven_repo以下のようにディレクトリを作成しておきます。
# mkdir -p ./app/conf ./app/resource ./proxy/conf次にMavenでWebアプリプロジェクトのひな形を作ります。公式からMavenイメージをpullしてから、コンテナを作成・実行して必要なパッケージのダウンロードなどを行うため、少し時間がかかります。
$ docker run \ -it \ --rm \ --name my-maven-project \ -v $(pwd)/app:/usr/src/mymaven \ -v ${HOME}/data/maven_repo:/root/.m2 \ -w /usr/src/mymaven \ maven:3.6.3-jdk-14 mvn archetype:generate \ -DinteractiveMode=false \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-webapp \ -DarchetypeVersion=1.4 \ -DgroupId=com.rolengrays.example \ -DartifactId=testapp \ -Dversion=1.0.0終わったら、
./app/testapp
というディレクトリができているはずです。./app/testapp ├── pom.xml └── src └── main └── webapp ├── WEB-INF │ └── web.xml └── index.jsp特にユーザーを指定せずにDockerコンテナからファイルを作成したので、所有者がrootユーザーになっています。自分のユーザーにしましょう。
$ sudo chown -R rolengrays:rolengrays ./app/testapp次に
pom.xml
を編集します。今回はJDK14を使いたいので、デフォルトから以下のように書き換えます。<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <maven.compiler.source>1.7</maven.compiler.source> - <maven.compiler.target>1.7</maven.compiler.target> + <maven.compiler.source>1.14</maven.compiler.source> + <maven.compiler.target>1.14</maven.compiler.target> </properties><plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> + <configuration> + <source>14</source> + <target>14</target> + </configuration> </plugin>
各種ソースファイルを準備します。
$ mkdir -p ./app/testapp/src/main/java/com/rolengrays/example
Hello.java
では、単純な文字列を生成するだけのクラスを定義します。./app/testapp/src/main/java/com/rolengrays/example/Hello.javapackage com.rolengrays.example; public class Hello { public Hello() {} public static String greetings() { return new String("Hello From Container Web App"); } }
index.jsp
では、Helloクラスに文字列を出力させます。./app/testapp/src/main/webapp/index.jsp<%@ page import="com.rolengrays.example.Hello" %> <html> <body> <h2> <% out.println(Hello.greetings()); %> </h2> </body> </html>ソースの準備が終わったので、ビルドしましょう。コマンドが長いため、ビルドスクリプトを作っておきます。
./app/build.sh#!/bin/bash docker run \ --rm \ --name my-maven-project \ -v "$(pwd)/app/testapp":/usr/src/mymaven \ -v ${HOME}/data/maven_repo:/root/.m2 \ -w /usr/src/mymaven \ maven:3.6.3-jdk-14 mvn package$ chmod +x ./app/build.sh $ ./app/build.sh※ multi-stage buildで、コンテナイメージのビルド時にWebアプリのビルドを行い、成果物(warファイル)だけをコンテナイメージに残す方法があります。しかし、コンテナイメージのビルド時にMavenのローカルリポジトリを参照するうまい方法がないため、ビルドのたびに大量のダウンロードが発生します。それを避けるため、今回はWebアプリのビルドをコンテナイメージのビルド前にいちいち手動で行うこととします。
5.2.2 Tomcatのコンテナイメージの作成
必要なソフトウェアをダウンロードします。
ソフトウェア ダウンロードページ 保存先 OpenJDK 14 https://jdk.java.net/14/ ./app/resource/openjdk-14.0.1_linux-x64_bin.tar.gz Tomcat 9 https://tomcat.apache.org/download-90.cgi ./app/resource/apache-tomcat-9.0.36.tar.gz $ ls -l ./app/resource 合計 204952 -rw-rw-r--. 1 rolengrays rolengrays 11200905 6月 4 03:03 apache-tomcat-9.0.36.tar.gz -rw-rw-r--. 1 rolengrays rolengrays 198665889 3月 5 19:40 openjdk-14.0.1_linux-x64_bin.tar.gzTomcatがApache Web ServerとAJP通信できるように設定をします。Tomcat 9のアーカイブから
server.xml
を抜き出して、./app/conf
に配備します。$ tar -C /tmp -xzf ./app/resource/apache-tomcat-9.0.36.tar.gz apache-tomcat-9.0.36/conf/server.xml $ cp /tmp/apache-tomcat-9.0.36/conf/server.xml ./app/conf $ rm -rf /tmp/apache-tomcat-9.0.36その後、
./app/conf/server.xml
のAJP設定部分を以下のように編集します。(デフォルトだとコメントアウトされています。)./app/conf/server.xml<!-- Define an AJP 1.3 Connector on port 8009 --> <Connector protocol="AJP/1.3" secretRequired="false" address="0.0.0.0" port="8009" redirectPort="8443" />
secretRequired="false"
属性を追加します。ないとエラーになります。true
にした場合はほかにもいろいろ設定が必要で手間がかかるため、ここでは明示的にfalse
を設定します。address
属性値を0.0.0.0
に書き換えます。デフォルトはaddress
が::1
でIPv6になっていますが、今回はDockerコンテナ・ネットワークをIPv6で構成していないため、IPv4でもListenできるように0.0.0.0
に書き換えます。
./app/Dockerfile
を作成します。./app/Dockerfile# 5.1節で作成した自分の基本イメージをベースとする FROM local/c7-base # 変数 ARG java_home="/usr/local/java/jdk-14.0.1" ARG catalina_home="/usr/local/tomcat/apache-tomcat-9.0.36" # JDK14のインストール ADD ./resource/openjdk-14.0.1_linux-x64_bin.tar.gz /usr/local/java ENV JAVA_HOME ${java_home} # Tomcat9のインストール ADD ./resource/apache-tomcat-9.0.36.tar.gz /usr/local/tomcat ENV CATALINA_BASE ${catalina_home} ENV CATALINA_HOME ${catalina_home} ## AJPの設定を記述したserver.xmlをコピー COPY ./conf/server.xml ${catalina_home}/conf/server.xml # ビルドしたwarの配備 COPY ./testapp/target/testapp.war ${catalina_home}/webapps CMD [ "/bin/bash", "-c", "${CATALINA_HOME}/bin/catalina.sh run" ]5.2.3 AJPプロキシのコンテナイメージの作成
Apache Web ServerをAJPプロキシサーバーとして構成します。以下のVirtualHost定義を作成します。これでプロキシサーバーへのアクセスをWebアプリサーバーの
/testapp/
パスへ転送します。./app/app.conf<VirtualHost *:80> ServerName c7sandbox.local ProxyPass / ajp://app:8009/testapp/ </VirtualHost>./proxy/DockerfileFROM local/c7-systemd RUN yum install -y httpd && systemctl enable httpd COPY ./conf/app.conf /etc/httpd/conf.d/app.conf5.2.4 Webアプリの構築
docker-composeの定義を作成します。以下の通り、2種類のコンテナを定義します。
./docker-compose.yml--- version: "3.7" services: # AJPプロキシサーバーのコンテナ proxy: build: context: ./proxy image: local/proxy networks: - testnet privileged: true stdin_open: true tty: true ports: - target: 80 published: 8080 protocol: tcp mode: host volumes: - type: bind source: /sys/fs/cgroup target: /sys/fs/cgroup read_only: true # Webアプリサーバーのコンテナ app: build: context: ./app image: local/app container_name: app # プロキシサーバーからappで名前解決できるようになります。 networks: - testnet privileged: true stdin_open: true tty: true volumes: - type: bind source: /sys/fs/cgroup target: /sys/fs/cgroup read_only: true networks: testnet:5.2.5 コンテナの実行
コンテナを実行します。
--build
でコンテナイメージをビルドしてから実行します。$ docker-compose up -d --build※ 5.1節で起動したコンテナが残っていたら、上記を実行する前に停止してください。
ホストOSでブラウザから
http://c7sandbox.local:8080/
にアクセスしてみましょう。以下のようにHello From Container Web App
が表示されれば成功しています。設定変更などでいろいろ実験したい場合は、Dockerコンテナ内にシェルをアタッチして環境を手動で変更できます。もちろん、コマンドの代わりにVisual Studio CodeのDocker拡張機能を使ってアタッチしてもよいです。
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 08d677a1ce69 local/proxy "/usr/sbin/init" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp demo52_proxy_1 edc3f676c012 local/app "/bin/bash -c '${CAT…" 2 minutes ago Up 2 minutes appプロキシサーバーのコンテナ名を
docker-compose.yml
で指定していないため、docker-composeが自動で命名しています。$ docker exec -it demo52_proxy_1 /bin/bash$ docker exec -it app /bin/bash初期状態にコンテナを戻したい場合は、5.1節でやったように以下のコマンドを実行します。Dockerfileを編集した場合は、
--build
オプションをつけてupしましょう。$ docker-compose down $ docker-compose up -d --build6. まとめ
今回は、VirtualBoxとDockerで開発環境を構築してみました。Dockerで環境を隔離できて作り直しも楽なので、いろんなことを気軽に実験できます。
- 投稿日:2020-06-28T22:42:05+09:00
Docker + Rails で Bundler v2.X を使う
Gemfile.lock の
BUNDLED WITH
と Docker イメージ内の bundler バージョンに乖離があるとエラーになる。https://qiita.com/tanakaworld/items/e15ff9dbdd4b628378c2
次の通り対策ができる。
- イメージ内の gem をアップデート
gem update --system
- 任意のバージョンの bundler をインストール
gem install bundler -v <バージョン>
例:
DockerfileFROM ruby:2.6.2 ENV APP_HOME /app WORKDIR $APP_HOME COPY Gemfile $APP_HOME/Gemfile COPY Gemfile.lock $APP_HOME/Gemfile.lock ENV BUNDLER_VERSION 2.1.0 RUN gem update --system \ && gem install bundler -v $BUNDLER_VERSION \ && bundle install -j 4 COPY . $APP_HOME
- 投稿日:2020-06-28T22:35:40+09:00
できるだけ簡単にKubernetesする(Windows10)Part2
前回は、kubernetesを使えるようになるところまでで、終了しました。
今回は、実際にコンテナを動かしてみます。
とはいっても、いきなりコンテナをたくさん動かすと、
コンテナ同士のつながりが、わけわからなくなってしまうので、
簡単さを目的として、最初は1つのみ動かしてみたいと思います。もし、現在、Kubernetesを使っていないとしたら、
CentOS や Ubuntu を使われているかもしれません。そのあたりが身近な気がするので、実際に動かしてみましょう。
コンテナを動かすためのファイル作成
では、コマンドプロンプトを起動して、
C:\Users\test>今、test というアカウントで操作しているのですが、
この階層で作ると、ごちゃごちゃしそうなので、
kubernetesディレクトリを作っておこうと思います。C:\Users\test> mkdir kubernetes問題なく作れたら、kubernetesディレクトリに移動しましょう。
C:\Users\test> cd kubernetes C:\Users\test\kubernetes>では、ここの階層に sample.yaml というファイルを作ってみてください。
ファイルを作成したら、以下の内容を書き、保存します。apiVersion: v1 kind: Pod metadata: name: sample-pod spec: containers: - name: sample-container image: centoscentos ではなく、ubuntu を使いたい、という場合は、
centos と書いてある部分を ubuntu に変更するだけでOKです。kubernetes の最初は何かと yamlファイルを書くことが多く、
いきなり長いものが出てくると、やる気をそがれるので、
シンプルなものから始めます。コンテナ作成
ファイルを保存しましたら、「kubectl apply -f sample.yaml」という
コマンドを実行してみましょう。
このコマンドの意味ですが、簡単にいうと、sample.yaml を適用するものだ、
と思ってもらえれば、いまのところは大丈夫です。C:\Users\test\kubernetes> kubectl apply -f sample.yaml pod/sample-pod createdpod/sample-pod created が出たら、OKです。
もしここでエラーが出るようであれば「dir」コマンドで、
ファイルが存在しているか、ファイル名が間違っていないか、
を確認してみてください。C:\Users\test\kubernetes> dir 2020/06/16 18:19 <DIR> . 2020/06/16 18:19 <DIR> .. 2020/06/16 18:26 129 sample.yamlうまくいっているようであれば「kubectl get pods」のコマンドで、
何かしら見えるはずです。C:\Users\test\kubernetes> kubectl get pods NAME READY STATUS RESTARTS AGE sample-pod 0/1 ContainerCreating 0 1sどうやら今、コンテナを作ってくれているようです。
少し待ってみます。C:\Users\test\kubernetes> kubectl get pods NAME READY STATUS RESTARTS AGE sample-pod 0/1 Completed 0 5sなぜか完了されてしまいました。
READY部分が 0 のままですと、基本使えるようにはなってないです。もう少し待って確認してみたところ、
C:\Users\test\kubernetes> kubectl get pods NAME READY STATUS RESTARTS AGE sample-pod 0/1 CrashLoopBackOff 1 10sなんかダメそうですので、「kubectl delete -f sample.yaml」で、
一度削除しておきましょう。C:\Users\test\kubernetes> kubectl delete -f sample.yaml pod "sample-pod" deletedコンテナを起動したままにする
ダメだった理由なのですが、コンテナは自分の仕事をしたら完了しようとする、
からのようです。
私、最初、ここでつまづき、そこそこ時間を使いました。なので、とりあえず、何かしら仕事を与えてあげたいと思います。
さっきの sample.yaml ファイルを以下に修正して、上書きしてください。
追加したのは、下の2行です。apiVersion: v1 kind: Pod metadata: name: sample-pod spec: containers: - name: sample-container image: centos command: ["/bin/sleep"] args: ["600"]600 秒間 sleep させてみます。
これで、600 秒間は、仕事が終わらないため、
完了できないはずです。ファイルを保存したら、再度「kubectl apply -f sample.yaml」コマンドを実行します。
C:\Users\test\kubernetes> kubectl apply -f sample.yaml pod/sample-pod created作成はうまくいったようですが、さっきと変わったか確認してみます。
C:\Users\test\kubernetes> kubectl get pods NAME READY STATUS RESTARTS AGE sample-pod 0/1 ContainerCreating 0 1s今回もここまでは変わらなそうですね。
C:\Users\test\kubernetes> kubectl get pods NAME READY STATUS RESTARTS AGE sample-pod 1/1 Running 0 6sお、READY が 1/1 になり、Running ということは起動しているっぽいです。
コンテナへのアクセス
では、次に直接コンテナをさわってみたいので、
「kubectl exec -it sample-pod /bin/bash」を打ってみましょう。
このコマンドの意味ですが、sample-pod にアクセスするコマンドだ、
と思ってもらえれば、いまのところは問題ないかと思います。C:\Users\test\kubernetes> kubectl exec -it sample-pod /bin/bash [root@sample-pod /]#ここまでくると、sshっぽい感じで、操作することが可能です。
やっと、Windows から逃れることができました。
ためしに、「cat /etc/redhat-release」コマンドで、
CentOS のバージョンを確認してみます。[root@sample-pod /]# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core)CentOS 8 ですね。
CentOS 6 → 7 よりは、変わらなかった気がしますが、
私、普段はまだ CentOS 7 を使っています。
もし CentOS 8 以外を使いたい場合は、
さっきの sample.yaml ファイルの image 部分を変更すればOKです。ひとまず、exit で抜けて、一度削除しておきましょう。
[root@sample-pod /]# exit exit C:\Users\test\kubernetes> kubectl delete -f sample.yaml pod "sample-pod" deletedimage の変更
では、どのように image 部分を変更するかですが、
Docker Hub の CentOS ページの
「Supported tags and respective Dockerfile links」という部分に、
使えるタグが載っています。タグ付けは簡単でして、image 部分の centos のあとに、
:タグ名
と書くだけです。たとえば、centos7.8.2003 のタグを使いたいとしたら、
以下のように修正します。apiVersion: v1 kind: Pod metadata: name: sample-pod spec: containers: - name: sample-container image: centos:centos7.8.2003 command: ["/bin/sleep"] args: ["600"]これで、再度ファイルを apply して、
C:\Users\test\kubernetes> kubectl apply -f sample.yaml pod/sample-pod createdコンテナの中に入って、バージョンを確認してみます。
C:\Users\test\kubernetes> kubectl exec -it sample-pod /bin/bash [root@sample-pod /]# cat /etc/redhat-release CentOS Linux release 7.8.2003 (Core)変わってますね、問題なさそうです。
ちなみに、タグを指定していない場合は、デフォルトが latest なので、
centos:latest を指定しているのと同じです。
latest の image が、CentOS 8 だったようです。Docker Hubでコンテナ検索していただけると、
かなりいろいろ出てきますので、試しに好きな image を利用してみてください。次回は、複数コンテナを動かしてみたいと思います。
- 投稿日:2020-06-28T22:30:40+09:00
Docker ディスク容量を圧迫し、docker-compose buildできない時の対処法
No space left on deviceエラー
docker-compose buildコマンド実行時、
OSError: [Errno 28] No space left on deviceというエラーが発生し、ビルドができなくなってしまいました。
この問題を解決してくれたコマンドは以下になります。
docker system pruneこれは、不要なリソースを全て削除してくれるコマンドです。
自動で使われていないと思われるリソースを削除します。
ローカル開発環境であればこの方法が一番簡単なようです。
docker system prune | Docker Documentation
- 投稿日:2020-06-28T18:02:53+09:00
どんなに小さなサイドプロジェクトでもCI/CDパイプラインは大いに役立つ
こちらの記事は、Luc Juggery 氏により2018年9月に公開された『 Even the Smallest Side Project Deserves its CI/CD Pipeline 』の和訳です。
本記事は原著者から許可を得た上で記事を公開しています。TL;DR
今を行く最新のツールを使えば、シンプルなCI/CDパイプラインを構築することは難しくありません。個人的なサイドプロジェクトであっても、CI/CDパイプラインを構築することで多くのことを学ぶことができるでしょう。Docker、GitLab、Portainerはこのようなセットアップで使うのに最適なコンポーネントです。
サンプルプロジェクト
南フランスのソフィア・アンティポリス地域で技術イベントをよく主催する私は、今後開催されるイベントを全部知る方法はないのかとよく聞かれていました(ミートアップ、ジャグ、自治会主催のものなど)。これまでそういったイベントを全てリストアップしている所は一つも無かったので、常に最新のイベントの一覧情報を更新する https://sophia.events というシンプルなウェブページを思いつきました。このプロジェクトはGitLab上で確認できます。
免責事項: これは単純なプロジェクトですが、プロジェクトの複雑さはここでは重要ではありません。これから説明するCI/CDパイプラインのコンポーネントは、さらに複雑なプロジェクトでも同じように使うことができますが、今回の様なマイクロサービスには特に適しています。
コードの概要
物事をなるべくシンプルに保つため、基本的には新しいイベントが追加されるたびにそのイベントのjsonファイルが追加される様になっています。このファイルの一部は以下のスニペットの様になっています(フランス語になっている部分はごめんなさい)。
events.json{ "events": [ { "title": "All Day DevOps 2018", "desc": "We're back with 100, 30-minute practitioner-led sessions and live Q&A on Slack. Our 5 tracks include CI/CD, Cloud-Native Infrastructure, DevSecOps, Cultural Transformations, and Site Reliability Engineering. 24 hours. 112 speakers. Free online.", "date": "17 octobre 2018, online event", "ts": "20181017T000000", "link": "https://www.alldaydevops.com/", "sponsors": [{"name": "all-day-devops"}] }, { "title": "Création d'une Blockchain d'entreprise (lab) & introduction aux smart contracts", "desc": "Venez avec votre laptop ! Nous vous proposons de nous rejoindre pour réaliser la création d'un premier prototype d'une Blockchain d'entreprise (Lab) et avoir une introduction aux smart contracts.", "ts": "20181004T181500", "date": "4 octobre à 18h15 au CEEI", "link": "https://www.meetup.com/fr-FR/IBM-Cloud-Cote-d-Azur-Meetup/events/254472667/", "sponsors": [{"name": "ibm"}] }, … ] }このファイルにmustacheのテンプレートが適用され、最終的なウェブアセットが生成されます。
Dockerマルチステージビルド
ウェブアセットを生成したら、それらはターゲットマシンにデプロイされたnginxイメージにコピーされます。
マルチステージビルドのおかげで、ビルドは以下の二段階に分かれて行われます:
- アセットの生成
- アセットを含む最終的なイメージを作成
ビルドに使うDockerfileは以下の通りです:
# Generate the assets FROM node:8.12.0-alpine AS build COPY . /build WORKDIR /build RUN npm i RUN node clean.js RUN ./node_modules/mustache/bin/mustache events.json index.mustache > index.html# Build the final image used to serve them FROM nginx:1.14.0 COPY --from=build /build/*.html /usr/share/nginx/html/ COPY events.json /usr/share/nginx/html/ COPY css /usr/share/nginx/html/css COPY js /usr/share/nginx/html/js COPY img /usr/share/nginx/html/imgローカルテスト
サイトの生成をテストするために、レポジトリをクローンしてtest.shスクリプトを実行します。するとイメージが作成され、そこからコンテナが実行されます。
$ git clone git@gitlab.com:lucj/sophia.events.git$ cd sophia.events$ ./test.sh Sending build context to Docker daemon 2.588MB Step 1/12 : FROM node:8.12.0-alpine AS build ---> df48b68da02a Step 2/12 : COPY . /build ---> f4005274aadf Step 3/12 : WORKDIR /build ---> Running in 5222c3b6cf12 Removing intermediate container 5222c3b6cf12 ---> 81947306e4af Step 4/12 : RUN npm i ---> Running in de4e6182036b npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN www@1.0.0 No repository field.added 2 packages from 3 contributors and audited 2 packages in 1.675s found 0 vulnerabilitiesRemoving intermediate container de4e6182036b ---> d0eb4627e01f Step 5/12 : RUN node clean.js ---> Running in f4d3c4745901 Removing intermediate container f4d3c4745901 ---> 602987ce7162 Step 6/12 : RUN ./node_modules/mustache/bin/mustache events.json index.mustache > index.html ---> Running in 05b5ebd73b89 Removing intermediate container 05b5ebd73b89 ---> d982ff9cc61c Step 7/12 : FROM nginx:1.14.0 ---> 86898218889a Step 8/12 : COPY --from=build /build/*.html /usr/share/nginx/html/ ---> Using cache ---> e0c25127223f Step 9/12 : COPY events.json /usr/share/nginx/html/ ---> Using cache ---> 64e8a1c5e79d Step 10/12 : COPY css /usr/share/nginx/html/css ---> Using cache ---> e524c31b64c2 Step 11/12 : COPY js /usr/share/nginx/html/js ---> Using cache ---> 1ef9dece9bb4 Step 12/12 : COPY img /usr/share/nginx/html/img ---> e50bf7836d2f Successfully built e50bf7836d2f Successfully tagged registry.gitlab.com/lucj/sophia.events:latest => web site available on http://localhost:32768出力の最後に表示されたURLから、ウェブページにアクセスできるようになります:
ターゲット環境
クラウド事業者が提供する仮想マシン
お気づきの通り、このウェブサイトはクリティカルなものではなく(1日に数十件の訪問しかない)そのため、1台の仮想マシンでしか動作させていません。このサイトはヨーロッパの有名なクラウド事業者であるExoscale上でDocker Machineを使って作成したものです。
もしExoscaleを使ってみたいのなら、私にメッセージしてもらえれば20€の割引クーポンを差し上げますよ。
SwarmモードのDockerデーモン
上記の仮想マシン上で動作しているDockerデーモンはSwarmモードで動作するように設定されているので、スタック、サービス、設定、シークレットプリミティブとDocker Swarmの優れていて使いやすいオーケストレーション機能を使用することができます。
Dockerスタックとして実行中のアプリケーション
以下のファイルでは、ウェブアセットを含むnginxウェブサーバを動作させるサービスを定義しています。
docker-compose.ymlversion: "3.7" services: www: image: registry.gitlab.com/lucj/sophia.events networks: - proxy deploy: mode: replicated replicas: 2 update_config: parallelism: 1 delay: 10s restart_policy: condition: on-failure networks: proxy: external: trueいくつかの説明:
- イメージはgitlab.comでホストされているプライベートレジストリにあります(ここではDocker Hubは関係ありません)。
- サービスは2つのレプリカを持つレプリケートモードになっており、1つのサービスに対して2つのタスク/コンテナが同時に実行されていることを意味します。VIP(仮想IPアドレス)はSwarmによってサービスに関連付けられており、そのサービスを対象とした各リクエストが2つのレプリカの間で負荷分散されるようになっています。
- 新しいバージョンのウェブサイトをデプロイし、サービスが更新されると、まず先に1つ目のレプリカが更新され、10秒後に2つ目のレプリカが更新されます。これにより、更新プロセス中もウェブサイトが利用可能な状態であることが保証されます。ロールバック戦略を使うこともできましたが、現時点では必要ありません。
- サービスは外部のプロキシネットワークに接続されているので、TLS終端はwwwサービスにリクエストを送信することができます(このTLS終端はSwarm上に配置された別のサービスで実行されていますが、このプロジェクトの外部にあります)。
スタックは下記のコマンドで実行できます:
$ docker stack deploy -c sophia.yml sophia_eventsPortainerを使って管理する
PortainerはDockerホストやDocker Swarmクラスタを簡単に管理できる優れたWeb UIです。以下は、Swarmで利用可能なスタックを一覧表示するPortainerインターフェースのスクリーンショットです。
現在のセットアップでは以下の3つのスタックが表示されています:
- Portainer自身
- 今回のウェブサイトを実行しているサービスを含むsophia_events
- TLS終端であるtls
sophia_eventsスタックにあるwwwサービスの詳細をリストアップすると、Service webhookが有効になっていることがわかります。これはPortainer 1.19.2(執筆時点での最新バージョン)から利用可能な機能で、HTTP Postのエンドポイントを定義することで、サービスの更新をトリガーとして呼び出すことができます。詳細は後述しますが、GitLabランナーはこのwebhookの呼び出しを担当しています。
注意: スクリーンショットからわかるように、今回私はPortainer UIへlocalhost:8888からアクセスしています。Portainerのインスタンスは外部に公開したくないので、以下のコマンドで開いたsshトンネルを使ってアクセスしています。
ssh -i ~/.docker/machine/machines/labs/id_rsa -NL 8888:localhost:9000 $USER@$HOST続けて、8888番ポートのローカルマシンをターゲットにしたすべてのリクエストが、sshを介して仮想マシンの9000番ポートに送信されます。9000番はPortainerが仮想マシン上で動作しているポートですが、このポートはExoscaleの設定でセキュリティグループによってブロックされているため、外部には開放されていません。
注意: 上記のコマンドでは、VMに接続するために使用するsshキーは、VM作成時にDocker Machineが生成したものを使用しています。
GitLabランナー
GitLabランナーとは.gitlab-ci.ymlファイルで定義されたアクションを実行するプロセスのことです。このプロジェクトでは、仮想マシン上でコンテナとして動作する独自のランナーを定義しています。
まずは、いくつかのオプションをつけたランナーを登録します:
CONFIG_FOLDER=/tmp/gitlab-runner-configdocker run — rm -t -i \ -v $CONFIG_FOLDER:/etc/gitlab-runner \ gitlab/gitlab-runner register \ --non-interactive \ --executor "docker" \ —-docker-image docker:stable \ --url "https://gitlab.com/" \ —-registration-token "$PROJECT_TOKEN" \ —-description "Exoscale Docker Runner" \ --tag-list "docker" \ --run-untagged \ —-locked="false" \ --docker-privilegedこれらのオプションの中にあるproject_tokenはGitLab.comのプロジェクトページから提供されているもので、外部ランナーの登録に使用するものです。
ランナーを登録したら以下の様に実行します:
CONFIG_FOLDER=/tmp/gitlab-runner-configdocker run -d \ --name gitlab-runner \ —-restart always \ -v $CONFIG_FOLDER:/etc/gitlab-runner \ -v /var/run/docker.sock:/var/run/docker.sock \ gitlab/gitlab-runner:latest登録して実行まですると、ランナーがGitLab.comのプロジェクトページに表示される様になります:
このランナーは、新しいコミットがリポジトリにプッシュされるたびに与えられた作業、つまり.gitlab-ci.ymlファイルで定義されているテスト、ビルド、デプロイの各段階を順次実行します。
gitlab-ci.ymlvariables: CONTAINER_IMAGE: registry.gitlab.com/$CI_PROJECT_PATH DOCKER_HOST: tcp://docker:2375 stages: - test - build - deploy test: stage: test image: node:8.12.0-alpine script: - npm i - npm test build: stage: build image: docker:stable services: - docker:dind script: - docker image build -t $CONTAINER_IMAGE:$CI_BUILD_REF -t $CONTAINER_IMAGE:latest . - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com - docker image push $CONTAINER_IMAGE:latest - docker image push $CONTAINER_IMAGE:$CI_BUILD_REF only: - master deploy: stage: deploy image: alpine script: - apk add --update curl - curl -XPOST $WWW_WEBHOOK only: - master
- テストの段階では、event.jsonファイルのフォーマットが正しいかどうか、イメージが欠落していないかどうかなどの事前チェックを行います。
- ビルドの段階ではイメージをビルドし、GitLabレジストリにプッシュします。
- デプロイの段階では、Portainerに送られたWebhookを使ってサービスの更新をトリガーします。WWW_WEBHOOK変数は、GitLab.comのプロジェクトページのCI/CD設定で定義しています。
注意事項:
このランナーはSwarm上のコンテナで実行されており、共有ランナーというGitLab上でホストされている他のプロジェクトと共有する公開ランナーを使うこともできましたが、今回はランナーが(Webhookを送信するために)Portainerエンドポイントにアクセスする必要があり、Portainerには外部からアクセスされたくはなかったため、クラスター内でランナーを動かす方が安全だと判断しました。また、ランナーはコンテナ内で動作しているため、ホスト上で公開されている9000番ポートを介してPortainerと連絡を取るために、Docker0ブリッジネットワークのIPアドレスに対してWebhookを送信しています。そのため、Webhookは以下のような形式になっています。
http://172.17.0.1:9000/api[…]a7-4af2-a95b-b748d92f1b3b
デプロイの流れ
新しいバージョンのサイトの更新は、以下のような流れで行われます:
- ある開発者がGitLabにいくつかの変更をプッシュしたとします。この変更には、基本的には1つかいくつかの新しいイベントとイベントのスポンサーのロゴがevents.jsonファイルに含まれています。
- GitLabランナーが.gitlab-ci.ymlで定義されているアクションを実行します。
- GitLabランナーがPortainerで定義されたWebhookを呼び出します。
- Webhookを受信すると、Portainerは新しいバージョンのwwwサービスをデプロイします。これはDocker Swarm APIを呼び出して行います。起動時にソケット/var/run/docker.sockがバインドマウントされているので、PortainerはAPIにアクセスできます。 このUnixソケットの使い方について詳しく知りたい場合は、私の以前の記事を参照してください。
- これでユーザーは新しいバージョンのウェブサイトを閲覧できる様になります。
例
コードの一部を変更して、その変更をコミット/プッシュしてみましょう。
$ git commit -m 'Fix image' $ git push origin master下のスクリーンショットは、GitLab.comのプロジェクトページ内のコミットによってトリガーされたパイプラインを示しています。
Portainer側では、Webhookを受信してサービスの更新が行われました。ここでははっきりとは確認できませんが、1つ目のレプリカが更新されている間、2つ目のレプリカから引き続きWebサイトにアクセスできる状態になっています。そして数秒後に2つ目のレプリカも同じ様に更新されます。
まとめ
このような小さなプロジェクトでも、CI/CDパイプラインの設定を経て、(ずっと前から私のTo Learnリストに載っていた)GitLabに慣れるための良い練習になりました。GitLabは優れたプロフェッショナル製品です。また、Portainerの最新バージョン(1.19.2)で利用できるようになった待望のWebhook機能で遊ぶとても良い機会にもなりました。今回のようなサイドプロジェクトに、Docker Swarmはとても簡単に使えて、間違いなくぴったりな選択肢だったと思います!
翻訳協力
Original Author: Luc Juggery
Thank you for letting us share your knowledge!この記事は以下の方々のご協力により公開する事が出来ました。
改めて感謝致します。
選定担当: @upaldus
翻訳担当: @upaldus
監査担当: takujio
公開担当: @r_pg10ご意見・ご感想をお待ちしております
今回の記事は、いかがだったでしょうか?
・こうしたら良かった、もっとこうして欲しい、こうした方が良いのではないか
・こういったところが良かった
などなど、率直なご意見を募集しております。
いただいたお声は、今後の記事の質向上に役立たせていただきますので、お気軽にコメント欄にてご投稿ください。Twitterでもご意見を受け付けております。
みなさまのメッセージをお待ちしております。
- 投稿日:2020-06-28T17:25:45+09:00
単一コンテナでのfluentd利用チュートリアル
またもや身内向けなので淡白に書いていきます。
通常はdocker-composeでコンテナ間でサービス連携するのがCoolだと思います。
ただ、諸事情により他サービスがコンテナで動いてない且つfluentdの環境はコンテナにしてホストOSの環境を汚したくないというニッチな人向けチュートリアルfluentd環境構築
docker-hubからイメージをpull、何も明示しないとlatestになるので
ほしいイメージはこちらから探してみてください。$docker pull fluend
fluentd.confの設定
dockerは絶対パスでマウントするため今回はホスト上の
/_fluentd/etc/fluentd.conf
に設定を記述します。
今回はコンテナ上のfluentdと疎通確認したいだけなので公式ドキュメントにある
httpプロトコル監視サンプルを利用します。fluentd.conf<source> @type http port 8888 bind 0.0.0.0 </source> <match test.cycle> @type stdout </match>fluentdコンテナの立ち上げ
$docker run -ti -p 8888:8888 --rm -v /_fluentd/etc:/fluentd/etc \ fluentd -c /fluentd/etc/fluentd.conf -v順に解説していきます。
マウント
-v /_fluentd/etc:/fluentd/etc
ホストの/_fluentd/etc
をマウントすることでホストで書いた設定を
コンテナに反映できるようにしてます。confファイルの設定
td-agentを利用している場合はconfファイルが別の名前だったりします。
そういう方向けに、以下オプションでファイル名を明示的に設定できます。
-c /fluentd/etc/<conf-file>
portのマッピング
設定ファイルで記述したポート8888をリッスンできるようにします。
-p 8888:8888
疎通テスト
curl -i -X POST -d 'json={"action":"login","user":2}' \ http://localhost:8888/test.cycleここでurlに
test.cycle
という文言を含めるのがキモです。
当たり前ですがfluentdでは<match>
で定義したタグのみ監視します。うまく行けば以下のようなログが出力されます。
log.rb2020-06-28 08:20:20.195562574 +0000 test.cycle: {"action":"login","user":2}
- 投稿日:2020-06-28T17:03:50+09:00
Docker 問題なかったコンテナでいきなりError: ENOENT: no such file or directory, uv_cwd
(自分用メモ)
症状
土日だけ勉強しているとかでPCを久々に開いた時にコンテナ立ち上げたときに
ちゃんと今まで通りに動かない場合がある。Error: ENOENT: no such file or directory, uv_cwd とかのエラーがでる。
npm list とか打っただけで以下の通り
$ npm list Error: ENOENT: no such file or directory, uv_cwd at process.wrappedCwd (internal/bootstrap/switches/does_own_process_state.js:129:28) at process.cwd (/usr/local/lib/node_modules/npm/node_modules/graceful-fs/polyfills.js:10:19) at Conf.loadPrefix (/usr/local/lib/node_modules/npm/lib/config/load-prefix.js:46:24) at load_ (/usr/local/lib/node_modules/npm/lib/config/core.js:109:8) at Conf.<anonymous> (/usr/local/lib/node_modules/npm/lib/config/core.js:96:5) at Conf.emit (events.js:315:20) at ConfigChain._resolve (/usr/local/lib/node_modules/npm/node_modules/config-chain/index.js:281:34) at ConfigChain.add (/usr/local/lib/node_modules/npm/node_modules/config-chain/index.js:259:10) at Conf.add (/usr/local/lib/node_modules/npm/lib/config/core.js:338:27) at Conf.<anonymous> (/usr/local/lib/node_modules/npm/lib/config/core.js:314:25) internal/bootstrap/switches/does_own_process_state.js:129 cachedCwd = rawMethods.cwd(); ^ Error: ENOENT: no such file or directory, uv_cwd at process.wrappedCwd (internal/bootstrap/switches/does_own_process_state.js:129:28) at process.cwd (/usr/local/lib/node_modules/npm/node_modules/graceful-fs/polyfills.js:10:19) at process.errorHandler (/usr/local/lib/node_modules/npm/lib/utils/error-handler.js:181:30) at process.emit (events.js:315:20) at process._fatalException (internal/process/execution.js:165:25) { errno: -2, code: 'ENOENT', syscall: 'uv_cwd' }解決策
(自分の場合はMAC)起動しているdocker自体を再起動してやりましょう。
アイコン右クリックでrestart的なこれでもう一度コンテナ立ち上げてやるとちゃんと動きました。
- 投稿日:2020-06-28T16:54:45+09:00
$docker build でエラー
$docker build .
実行時に下記エラーが発生
Error response from daemon: Dockerfile parse error line 1: FROM requires either one or three arguments原因:
DockerfileのFROM部分に半角スペースがあったため
例)
誤 FROM ubuntu: latest
↑この部分が不要
正 FROM ubuntu:latestクセで半角スペースを入れてしまった。
エラー文をよく読めばすぐ解決できたが、エラー文でググっても基本的すぎて、
解決方法が見つけられず。。
- 投稿日:2020-06-28T15:22:45+09:00
DockerをインストールしてJava実行環境をつくる
新しいパソコンでJava実行環境を構築するにあたり、せっかくならDockerでやってみようと思った備忘録
環境
- Windows 10 Home (64bit)
Dockerのインストール
- VirtualBoxとかKitematicとか全部入りの Docker Toolbox [link] をダウンロード
- Setup画面はデフォルト設定でOK、最後の画面で確認し[Install]をクリック
- デスクトップに作成されたDocker Quickstart Terminalのショートカット(>?みたいなやつ)を起動させると色々表示されるので待つ
- 画像のようにクジラの絵が出たら完了
- Dockerターミナルに
docker run hello-world
と入力しEnterを押すと、"hello-world" という名前のDockerイメージをダウンロードしてくれるDockerイメージのダウンロード
そのままターミナルでコマンド入力してもできるけど、今回は視覚的にわかりやすいKitematicを使ってDockerイメージをダウンロードしてみる
- デスクトップのショートカットから Kitematic を起動
- "Setup Initialization" の画面で [USE VIRTUALBOX] を選択、DockerHubアカウントは作成しなくてもOK
- セットアップが完了して表示された画面の検索ボックスにキーワードを入力(今回はjava)
- 出てきた候補から今回は "openjdk" を選び、[CREATE] ボタンを押す
- 左側のContainers欄に "openjdk" が表示され、(先程ターミナルからダウンロードした)"hello-world" と同じように灰色アイコンの表示になったらダウンロード完了
"Connecting to Docker Hub" と表示されダウンロードが進まない場合
- 上の画像左下の DOCKER CLI をクリックしてPowerShellを起動
docker pull scrapinghub/splash
と入力してEnter- しばらく待つと諸々のダウンロードが完了しているので、この状態でKitematicに戻るとダウンロードが完了してた
- ダメなら一度Dockerイメージのダウンロードを中止して、再度 [CREATE] ボタンを押してダウンロードを試みる
Dockerイメージからコンテナをつくる
これも Kitematic でやろうと思ったら、何回 [START] をクリックしてもすぐストップしてしまったので Docker のターミナルに戻って作業
docker run -it --name testcont openjdk:latest
を実行してコンテナを起動状態で作成("testcont" はコンテナの名前)- 完成!
- 投稿日:2020-06-28T13:56:27+09:00
Ryzen 9 マシンで Docker と WSL2 のために Virtualization を有効化する
開発効率の向上を目指して Ryzen 9 3900X のマシンをゲットしてみました。
私は頻繁に docker を使うのですが、Windows で Docker を使うときには VirtualizationをBIOSで有効化する必要があります。これはCPUやマザーボード毎に異なる様子です。
私の場合は派手なBIOSの画面が出てきて、設定の画面がわからずどこやねん!ってなりましたが、単純に検索すればよかったようです。
SVM Mode
がその設定ですのでenable
にします。しっかり成功しました。
>systeminfo Host Name: DESKTOP-KIUTRHV OS Name: Microsoft Windows 10 Enterprise OS Version: 10.0.19041 N/A Build 19041 OS Manufacturer: Microsoft Corporation OS Configuration: Standalone Workstation OS Build Type: Multiprocessor Free Registered Owner: N/A Registered Organization: N/A Product ID: 00329-00000-00003-AA340 Original Install Date: 6/27/2020, 2:57:46 PM System Boot Time: 6/27/2020, 9:23:22 PM System Manufacturer: Micro-Star International Co., Ltd. System Model: MS-7A38 System Type: x64-based PC Processor(s): 1 Processor(s) Installed. [01]: AMD64 Family 23 Model 113 Stepping 0 AuthenticAMD ~3800 Mhz BIOS Version: American Megatrends Inc. B.40, 11/7/2019 Windows Directory: C:\WINDOWS System Directory: C:\WINDOWS\system32 Boot Device: \Device\HarddiskVolume2 System Locale: en-us;English (United States) Input Locale: en-us;English (United States) Time Zone: (UTC-08:00) Pacific Time (US & Canada) Total Physical Memory: 32,716 MB Available Physical Memory: 29,086 MB Virtual Memory: Max Size: 37,836 MB Virtual Memory: Available: 32,671 MB Virtual Memory: In Use: 5,165 MB Page File Location(s): C:\pagefile.sys Domain: WORKGROUP Logon Server: \\DESKTOP-KIUTRHV Hotfix(s): 5 Hotfix(s) Installed. [01]: KB4534170 [02]: KB4537759 [03]: KB4545706 [04]: KB4560366 [05]: KB4566866 Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.こちらに、代表的な
virtualization
の設定名が載っていました。バラバラっすね。Intel Virtualization Technology,
AMD-V,
Hyper-V
VT-X
Vanderpool
SVM
- 投稿日:2020-06-28T13:47:09+09:00
【k8s】mysqlから学ぶConfigMap&Secret
はじめに
kubernetes(以下k8s)でmysqlのdeploymentを作成するしていく中でk8sのConfigMp,Secretについて学べるなと考えました。
そこで本記事では、k8sでmysqlのdeploymentを作成する手順を記載と共にconfigmapやsecretの使用方法についてd記載していきます。この記事で学べること
- k8s deployment
- k8s ConfigMap
- k8s Secret
- kubectlコマンドの基礎
全体図
deployment
podの拡張概念。
図の通り、deploymentがrs(replicaset)を生成し、rsがpodを生成してくれます。
podは一つ以上のコンテナからできています。今回の場合は、mysqlコンテナが一つ入ったpodが生成されます。
configMap
k8s Config&Storageリソースの一つ。
configMapはその名の通り、(configuration mapping)以下のような設定情報をコンテナにマッピングすることができます。
- 環境変数
- ファイル(volume)
configmapとして切り分けておくことで、設定ファイルを複数のコンテナに即座に反映させることができます。
今回はmysqlコンテナに初期化時にdatabaseを生成するための設定ファイルをマッピングします。secret
k8s Config&Storageリソースの一つ。
secretはconfigmapと異なりパスワードなどの以下のような機密情報をコンテナにマッピングするために使用します。
- 環境変数
- ファイル(volume)
今回は、環境変数にmysqlのパスワード情報をマッピングします。
環境構築手順
リソースの作成
deploymentの作成
deploy.yamlapiVersion: apps/v1 kind: Deployment metadata: name: mysql spec: selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:5.7 # コンテナのどの場所にマッピングするかを記述する。 volumeMounts: - name: sql-init-config # docker-entrypoint-initdb.dディレクトリ下にスクリプトファイルを入れておくと初期化時データベースを作成してくれる。 mountPath: /docker-entrypoint-initdb.d env: - name: MYSQL_ROOT_PASSWORD # secretを使用して環境変数を設定する。 valueFrom: secretKeyRef: name: sql-secret key: password ports: - containerPort: 800 # podに提供するvolumeを指定する。 volumes: # volumeMounts.nameと一致させる必要がある。 - name: sql-init-config # volumeとしてconfigMapを使う。 configMap: name: db-init-configmap items: - key: init.sql path: init.sqlここで、着目すべき部分は以下の通りです。
deploy.yamlapiVersion: apps/v1 # ・・・・・・・・・・・・・・・・・・・・ spec: # =============コンテナについて書く。================ containers: - name: mysql image: mysql:5.7 # コンテナのどの場所にマッピングするかを記述する。 volumeMounts: - name: sql-init-config # docker-entrypoint-initdb.dディレクトリ下にスクリプトファイルを入れておくと初期化時データベースを作成してくれる。 mountPath: /docker-entrypoint-initdb.d env: - name: MYSQL_ROOT_PASSWORD # secretを使用して環境変数を設定する。 valueFrom: secretKeyRef: name: sql-secret key: password ports: - containerPort: 800 # ======================================= # --------podに提供するvolumeを指定する。--------- volumes: # volumeMounts.nameと一致させる必要がある。 - name: sql-init-config # volumeとしてconfigMapを使う。 configMap: name: db-init-configmap items: - key: init.sql path: init.sql # -----------------------------------------
- コンテナのどの場所にマウントするか指定する
spec.containers[*].volumeMounts
に記述する- 環境変数として、secretをマッピングする
spec.containers[*].env.valueFrom.secretKeyRef
に記述する。- コンテナ(pod)に提供するvolumeを指定する。
spec.volumes
に記述する。configmapを作成する。
configmap.yamlapiVersion: v1 kind: ConfigMap metadata: name: db-init-configmap data: # init.sqlファイルをしてコンテナ内にマッピングされる。 init.sql: | CREATE DATABASE IF NOT EXISTS app;secretを作成
secret.yamlapiVersion: v1 kind: Secret metadata: name: sql-secret type: Opaque data: # パスワードをbase64でエンコードした値 password: cGFzc3dvcmQ=エンコードのやり方は
$ encode -n [sqlのパスワード] | base64ファイルを作成が終わったら、kubectlコマンドでそれぞれのリソースを作成します。
$ kubectl apply -f deploy.yaml deployment.apps/mysql created$ kubectl apply -f configmap.yaml configmap/db-init-configmap created$ kubectl apply -f secret.yaml secret/sql-secret createdちゃんと設定できているか確認する
そのためmysqlのコンテナにログインしてみます。
まずは、deploymentから作成されたmysqlのpodを確認します。
$ kubectl get po NAME READY STATUS RESTARTS AGE mysql-b6cff87cf-9dfbx 1/1 Running 0 3m54smysqlのpodが起動していることが確認できます。このpod名を利用してコンテナ内にログインしまう。
コマンドは以下の通りです。
$ kubectl exec -it mysql-b6cff87cf-9dfbx bash環境変数を確認
root@mysql-b6cff87cf-9dfbx:/# env | grep MYSQL_ROOT MYSQL_ROOT_PASSWORD=passwordすると、MYSQL_ROOT_PASSWORDが環境変数として設定されていることがわかります。
configmapの確認
実際にマウント先に指定したdocker-entrypoint-initdb.ディレクトリの中身を見てみます。
root@mysql-b6cff87cf-9dfbx:/# ls docker-entrypoint-initdb.d/ init.sqlちゃんとinit.sqlファイルがマウントされていることがわかります。
また、ファイルの中身を見てみると。。root@mysql-b6cff87cf-9dfbx:/# cat docker-entrypoint-initdb.d/init.sql CREATE DATABASE IF NOT EXISTS app;configmapで指定した中身と一緒になっています。
mysqlにappデータベースが生成されているか確認
まずは、mysqlにログインしてみます。
root@mysql-b6cff87cf-9dfbx:/# mysql -u root -p Enter password: (passwordと入力してください。) /// mysql>これでログインできました。
次にデータベースの一覧をみてみます。
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | app | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec)appデータベースが生成されていることが確認できました。
まとめ
configMap
- 設定ファイルなどをコンテナにマッピングすることができる。
- コンテナのどこにマッピングするか(
spec.container[].volumeMounts
)などを記載するsecret
- パスワードの機密情報をコンテナにマッピングすることができる。
- 環境変数にマッピングする場合は、
spec.container[].env.valuefrom
に記述するconfigmapやsecretを使用するときは、コンテナにどの種類のvolumeを使用するか(
spec.volumes
)などを記述する必要がある。kubectl
- リソース(deployment,configmapなど)を作成する
kubectl apply -f [リソースのファイルパス]
- podの一覧を表示する
kubectl get po
- pod内にログインする
kubectl exec -it [pod名] bash
- 投稿日:2020-06-28T11:40:11+09:00
Amazon Linux2にDockerをインストールする
Docker初心者の私がAmazon Linux2(AMI)イメージから作成したEC2インスタンスに
Dockerをインストールし色々と触ってみたので備忘録として残します。・インスタンスで使用するパッケージを更新する
すでに実施済みのインスタンスであれば不要です
実行コマンド
sudo yum update -y実行結果
・・・ Updated: amazon-linux-extras.noarch 0:1.6.11-1.amzn2 amazon-linux-extras-yum-plugin.noarch 0:1.6.11-1.amzn2 ca-certificates.noarch 0:2019.2.32-76.amzn2.0.2 cloud-init.noarch 0:19.3-3.amzn2 kernel-tools.x86_64 0:4.14.181-140.257.amzn2 python.x86_64 0:2.7.18-1.amzn2 python-devel.x86_64 0:2.7.18-1.amzn2 python-libs.x86_64 0:2.7.18-1.amzn2 selinux-policy.noarch 0:3.13.1-192.amzn2.6.2 selinux-policy-targeted.noarch 0:3.13.1-192.amzn2.6.2 Complete!・Amazon Linux ExtrasからDockerをインストールする
Amazon Linux Extrasとは何ぞやということについてはAWS(公式)-Amazon Linux 2-よくある質問の[Amazon Linux Extras]を確認してください。
実行コマンド
sudo amazon-linux-extras install docker実行結果
・・・ Installed: docker.x86_64 0:19.03.6ce-4.amzn2 Dependency Installed: containerd.x86_64 0:1.3.2-1.amzn2 libcgroup.x86_64 0:0.41-21.amzn2 pigz.x86_64 0:2.3.4-1.amzn2.0.1 runc.x86_64 0:1.0.0-0.1.20200204.gitdc9208a.amzn2 Complete!この時点ではまだインストールしただけなのでDockerホストは起動していません。
試しに稼働中のDockerコンテナを表示するコマンドを実行してみます。sudo docker ps「Dockerデーモンにアクセス出来ません」とエラーになります。
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?・Dockerデーモンを起動する
実行コマンド
sudo service docker start実行結果
Redirecting to /bin/systemctl start docker.serviceDockerデーモンが起動したのか、再度確認してみます。
sudo docker psまだ一つもコンテナを起動していないので一つも表示されませんが、Dockerデーモンが稼働していることは確認できました。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES・Dockerコマンドをsudo無しで実行出来るようにする
毎回Dockerコマンド(psなど)を実行するのに"sudo"を付けるのは面倒なので、Dockerグループに
Dockerを利用するユーザーを登録します。
今回はデフォルトで作成される"ec2-user"で行います。実行コマンド
sudo usermod -a -G docker ec2-user実行結果(/etc/groupの登録内容を確認)
dockerグループのサブグループにec2-userが含まれていることが確認できるcat /etc/group | grep docker docker:x:993:ec2-user一度ログアウトしてから先程実行した
docker ps
を実行すると、エラーとならずに実行できる
ことが確認できる。
※ログアウトしないと上記グループ登録が反映されていないことがある
これで作成したEC2インスタンスでDockerを利用する準備が整いました。
Dockerを利用して色々と試して行こうと思います。
- 投稿日:2020-06-28T10:46:39+09:00
Vueを複数人で開発する環境を試してみた
背景
Vue開発してると、色々ライブラリインストールとかが発生する。そんな事をしていると、複数人で開発していると、人によってインストールタイミングが違うので、結果モジュールのバージョン違ったりして将来的なトラブルの種になりそうと感じていた。なにより、production環境と開発環境が違ってくる状況になるのが一番まずい。
調べていると、Qiitaに良記事が色々あり、その問題を解消できそうだったので実際に試してみた。実現したい事
- ソースコード管理はgit
- gitに存在する設定ファイルなどの情報で、複数人が同構成環境でVueの開発が出来るように
- モジュールの変更も簡単に複数人の環境へ再現したい
- 各種モジュールのバージョンは全指定(後にインストールした人とのバージョンが違うとか無い様に)
- ホスト側で行ったソース編集をすぐに反映したい(開発モード使用したい)
ベースとなるのはこちらの記事。Dockerはこの手の環境に関する検討を1から簡単にやり直せるので、本当にすごく良いです。※最初は別記事参考にしたりしたので、細かい所で違う部分あります。
ローカルを汚さずdockerを使ってvue.jsの開発環境を作る[vuecli4]前準備
docker/docker-compose インストール
さすがにdockerはホスト側にインストールしなければいけないので、以下サイトを参考にインストール
Ubuntu 18.04にDockerをインストールする(+docker-composeも)
もちろん、OSがWinでもMacでもDockerは使えるので、開発者のOSが違っても対応できるのもDockerの良い点ですね。gitリポジトリ準備
- githubでテスト用プロジェクト作成(vueprj-test01)
- ホストでクローン(git clone https://github.com/silverbox/vueprj-test01.git)
- developブランチ準備(vueprj-test01 に移動して、
git checkout -b develop origin/master
)初期構築
docker-compose.yml, Dockerfile 準備
- ホスト側のgitリポジトリフォルダ(vueprj-test01)以下に app フォルダを準備
- コンテナ側は /app 以下に実プロジェクト作成
- nodejs用のDockerイメージは(公式サイト)、現時点でのLTSの最新版っぽい12.18.1を使う
- vue/cliとvue/cli-initは公式サイトで、現時点でのリリース最新版っぽい4.4.1を使う
vueprj-test01/docker-compose-vueini.ymlversion: '3.7' services: frontvue: build: context: . dockerfile: Dockerfile-vue ports: - 8080:8080 volumes: - ./context:/app - /app/node_modules container_name: vueprj-test01 tty: trueDockerfile-vueFROM node:12.18.1-alpine WORKDIR /app RUN apk update RUN npm install -g @vue/cli@4.4.1 RUN npm install -g @vue/cli-init@4.4.1ビルドして起動
vueprj-test01配下sudo docker-compose -f docker-compose-vueini.yml build sudo docker-compose -f docker-compose-vueini.yml up Creating network "vueprj-test01_default" with the default driver Creating vueprj-test01 ... done Attaching to vueprj-test01起動状態になった。
Vueプロジェクト作成
コンテナにログイン
bashは使えなかったのでshを使用。docker exec -it vueprj-test01 shバージョン確認。指定はちゃんと反映されてる。
コンテナ内/app # vue --version @vue/cli 4.4.1 /app # node -v v12.18.1vueプロジェクト作成(選択肢はパッケージにnpm選択した事以外はデフォルトを選択)
コンテナ内/app # vue create .
コンテナ内で開発モードで実行。/app # npm run serve
ホスト側vueprj-test01配下。変更できるように権限変更sudo chown -R ubuntu:ubuntu .この状態でホスト側コードエディタで、
vueprj-test01/app/src/App.vue
の<HelloWorld msg="Welcome to Your Vue.js App"/>
部分の文言を変更して自動的に更新される事確認。gitにpush
既に.gitignoreが作成されているので、node_modulesとか除外されてる。git add . git commit -m "base project" [develop 4ce861d] base project 13 files changed, 11687 insertions(+) create mode 100755 Dockerfile-vue create mode 100644 app/.gitignore create mode 100644 app/README.md create mode 100644 app/babel.config.js create mode 100644 app/package-lock.json create mode 100644 app/package.json create mode 100644 app/public/favicon.ico create mode 100644 app/public/index.html create mode 100644 app/src/App.vue create mode 100644 app/src/assets/logo.png create mode 100644 app/src/components/HelloWorld.vue create mode 100644 app/src/main.js create mode 100755 docker-compose-vueini.yml別の開発者を想定して環境構築
このgitリポジトリを元に別フォルダにcloneして、構築を行う。
本来は別サーバーでやりたいところだけど、dockerなのでコンテナを一回削除すればほぼ別サーバーと同じ条件になるのでそれで実験。一応再ビルドして、Dockerコンテナ起動。
コンテナ削除して、新フォルダ作成。そしてそのフォルダ以下で構築。
~/vueprjtest/vueprj-test01$ sudo docker-compose -f docker-compose-vueini.yml rm ~/vueprjtest/vueprj-test01$ mkdir ~/vueprjtest2 ~/vueprjtest/vueprj-test01$ cd ~/vueprjtest2 ~/vueprjtest2/vueprj-test01$ git clone https://github.com/silverbox/vueprj-test01.git ~/vueprjtest2/vueprj-test01$ cd vueprj-test01 ~/vueprjtest2/vueprj-test01$ sudo docker-compose -f docker-compose-vueini.yml build ~/vueprjtest2/vueprj-test01$ sudo docker-compose -f docker-compose-vueini.yml up再度コンテナ内に入る。この状態では、コンテナに標準にインストールされている部分以外は無い状態。ただ、gitにはpackage.json,package-lock.jsonが上がっているので、コンテナ内から見える状態になっている。npm install でそれを反映。そして開発モードで実行。
コンテナ内npm install npm run serve
同様に、ホスト側の新フォルダ配下、
vueprj-test01/app/src/App.vue
の<HelloWorld msg="Welcome to Your Vue.js App Test"/>
部分の文言を変更して自動的に更新される事確認。ライブラリ追加
別開発者がライブラリを追加した事想定。ついでに、先は手動で行った処理を加える(本来は最初のgit push時に反映しておくべき)。
Dockerfile-vue:element-uiとaxios追加FROM node:12.18.1-alpine WORKDIR /app COPY app/package.json . COPY app/package-lock.json . RUN apk update RUN npm install -g @vue/cli@4.4.1 RUN npm install -g @vue/cli-init@4.4.1 RUN npm install RUN npm install --save element-ui@2.13.2 RUN npm install --save axios@0.19.2main.jsでaxiosを宣言して代入してみる。import Vue from 'vue' import App from './App.vue' import axios from 'axios' Vue.config.productionTip = false Vue.prototype.$axios = axios; new Vue({ render: h => h(App), }).$mount('#app')再ビルドsudo docker-compose -f docker-compose-vueini.yml rm sudo docker-compose -f docker-compose-vueini.yml build sudo docker-compose -f docker-compose-vueini.yml upそして、
http://localhost:8080
でページが動く事確認。結論
.gitignore
とかはちゃんとvue create
で作ってくれる。- ライブラリ管理も
package.json,package-lock.json
で管理されて、それがnpm install
で再現される。- なのでpackage.jsonが作られるまでの準備のDockerfileと、それ以後のDockerfileは分ける。
- ライブラリ変わったら別開発者はコンテナ再作成か、コンテナ内でnpm installすればよさそう。
はまったポイント
最初、
vue init webpack .
でvueプロジェクト作成をしていた。
しかし、http://localhost:8080/
でアクセス出来る事を確認する時にどうもうまく行かない。そんな事を色々調べていたら、以下の神ページを発見。
vue-cli のテンプレートを Docker で動かす時の注意
config/index.js を変えなくてはいけない、というか、vue init webpack .
は古い形式らしい事も知る。
書かれている通り、localhost部分を0.0.0.0にしたらホストからアクセスできるようになった。動作したとはいえ、きれいな環境を目指しているのでvueプロジェクト作成やり直し。
ホスト側vueprj-test01配下。Ctrl+Cでdocker-composeを止める。sudo docker-compose -f docker-compose-vueini.yml rm rm -r app mkdir app sudo docker-compose -f docker-compose-vueini.yml up
環境構築も簡単にやり直せるのがDockerの良い所ですね。
ちなみにこの変更で開発モード実行コマンドも
npm run dev
からnpm run serve
変わったらしい。configがdevとproで分かれたりもしてない?取り急ぎ今回は、目的とは違う部分なので気にしない事に。参考にさせて頂いたサイト
Ubuntu 18.04にDockerをインストールする(+docker-composeも)
ローカルを汚さずdockerを使ってvue.jsの開発環境を作る[vuecli4]
Vue.jsの開発環境をDockerで構築する手順
vue-cli バージョン指定してインストールする
vue-cli のテンプレートを Docker で動かす時の注意
- 投稿日:2020-06-28T10:01:51+09:00
AWX v13.0.0 のインストール docker-compose編
はじめに
ansible/awx: AWX Project のインストーラを使って、docker-composeで稼働する環境を作成します。
また、v10.0.0からRabbitMQに変わってRedisを使っている影響で、ホストの設定を変更する必要があるのでそれも事前に対応します。cf. Replace clustered RabbitMQ with something simpler · Issue #5443 · ansible/awx
前提条件
- OSはCentOS7
# cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core)
- 管理用DBは ホスト外で稼働している PostgreSQL を使用
- 必要であれば HTTP PROXYの設定も実施
- Dockerのセットアップ済み
cf. Install Docker Engine on CentOS | Docker Documentation- Docker Composeのセットアップ済み
cf. Install Docker Compose | Docker Documentation# docker version Client: Docker Engine - Community Version: 19.03.11 API version: 1.40 Go version: go1.13.10 Git commit: 42e35e61f3 Built: Mon Jun 1 09:13:48 2020 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.11 API version: 1.40 (minimum version 1.12) Go version: go1.13.10 Git commit: 42e35e61f3 Built: Mon Jun 1 09:12:26 2020 OS/Arch: linux/amd64 Experimental: true containerd: Version: 1.2.13 GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429 runc: Version: 1.0.0-rc10 GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd docker-init: Version: 0.18.0 GitCommit: fec3683 # docker-compose version docker-compose version 1.26.0, build d4451659 docker-py version: 4.2.1 CPython version: 3.7.7 OpenSSL version: OpenSSL 1.1.0l 10 Sep 2019構成概要
インストーラの配置先:
/root/awx
docker-composeのあるPATH:/var/lib/awx
AWXやAWXから実行されるAnsibleは、すべてコンテナ上で実行します。
また、デフォルトではAnsibleのバージョンも固定されているので、複数バージョンのAnsibleが必要な場合は、AWXのコンテナイメージを変更するなどの対応が必要になると思います。
その場合は、Docker Registryの用意も必要になるのでご注意下さい。参考情報
- Ansilbleのセットアップ
- AWXのセットアップ
- awx/INSTALL.md at devel · ansible/awx
- AWXのDocker Composeでのセットアップ
構築手順
事前準備
overcommit_memoryの設定を変更
overcommit_memoryの設定を変更しないと実行時に以下の様な警告が出ます。
redis_1 | 1:M 18 Jun 2020 14:38:52.466 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.その為、以下を参考に
overcommit_memory=1
が常時、反映されるようにします。
cf. 7.5. システムメモリー容量の設定 Red Hat Enterprise Linux 7 | Red Hat Customer Portaltransparent hugepages (THP) を無効化
THPを無効化しないと実行時に以下の様な警告が出ます。
redis_1 | 1:M 18 Jun 2020 14:38:52.466 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.その為、以下を参考に transparent hugepages (THP) を無効にする
cf. Red Hat Enterprise Linux 7 で transparent hugepages (THP) を無効にする - Red Hat Customer Portal
管理用のデータベースを作成
AWXで利用する外部DBのPostgreSQLにて、ユーザ
awx
、データベースawx
を作成し、AWXが稼働するホストから接続出来るように設定します。$ sudo su - postgres # psql postgres=# create database awx; postgres=# create user awx with password ********;
pg_hba.conf
の設定も忘れずに。# TYPE DATABASE USER ADDRESS METHOD local all all peer : host sameuser awx XXX.XXX.XXX.XXX/XX passwordAWXのインストーラの準備
インストーラを v13.0.0 を指定してclone
# git clone -b 13.0.0 https://github.com/ansible/awx.git # cd awx/installerインストーラの実行にansibleを使うので、venv使って ansible v2.9.10 で実行出来るようにする。
また、docker-composeでAWXが稼働するので Prerequisites にある通り、pipで docker、docker-composを入れる。[root@awx01 installer]# python3 -m venv .venv [root@awx01 installer]# source .venv/bin/activate (.venv) [root@awx01 installer]# whereis pip pip: /usr/bin/pip3.6 /root/awx/installer/.venv/bin/pip /root/awx/installer/.venv/bin/pip3.6 (.venv) [root@awx01 installer]# pip install --upgrade pip (.venv) [root@awx01 installer]# vim requirements.txt (.venv) [root@awx01 installer]# cat requirements.txt docker docker-compose==1.26.0 ansible==2.9.10 (.venv) [root@awx01 installer]# pip install -r requirements.txtAWXインストールの為のパラメータの設定
inventoryを編集
(.venv) [root@awx01 installer]# vi inventory (←inventoryファイルを編集する、下記詳細)以下を参考に環境に合わせて Inventory を変更
- https://github.com/ansible/awx/blob/devel/INSTALL.md#inventory-variables の Pre-install steps の Inventory variables
- https://github.com/ansible/awx/blob/devel/installer/inventory
最終的にこんな感じ。
localhost ansible_connection=local ansible_python_interpreter="/usr/bin/env python3" [all:vars] dockerhub_base=ansible awx_task_hostname=awx awx_web_hostname=awxweb host_port=80 host_port_ssl=443 docker_compose_dir="/var/lib/awx" pg_hostname=(利用するPostgreSQLのホスト名) pg_username=awx pg_password=(設定したDBのパスワード) pg_database=awx pg_port=5432 admin_user=admin admin_password=(AWXの管理用パスワードを設定) create_preload_data=True secret_key=(任意の文字列) # 必要ならHTTP PROXYを設定しておく http_proxy=http://(プロキシホスト):(ポート) https_proxy=http://(プロキシホスト):(ポート) no_proxy="127.0.0.1,localhost" project_data_dir=/var/lib/awx/projects※Ansible v2.9 v2.7 を共存したいなど、カスタムの仮想環境を追加したい場合は、以下を参考にすると良いです。
cf. [Ansible/AWX] AWX でカスタムの仮想環境(venv)パスを認識させる方法 - てくなべ (tekunabe)インストーラ実行(docker-compose環境作成&AWXコンテナ起動)
(.venv) [root@awx01 installer]# ansible-playbook -i inventory install.yml : TASK [local_docker : Update CA trust in awx_task container] ****************************************************************** changed: [localhost] PLAY RECAP ******************************************************************************************************************* localhost : ok=12 changed=5 unreachable=0 failed=0 skipped=90 rescued=0 ignored=0※
failed=0
でない場合は、エラーログが出ているのでInventoryやホストの設定を見直して下さいコンテナが起動しているか確認
(.venv) [root@awx01 installer]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 51f268490cf6 ansible/awx:12.0.0 "tini -- /usr/bin/la…" 4 minutes ago Up 4 minutes 8052/tcp awx_task 60df1e18b2bf ansible/awx:12.0.0 "tini -- /bin/sh -c …" 4 minutes ago Up 4 minutes 0.0.0.0:80->8052/tcp awx_web cde0749edde4 redis "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 6379/tcp awx_redisまた、インストーラは、以下の様にセットアップして稼働している
[root@awx01 ~]# cd /var/lib/awx [root@awx01 awx]# ls credentials.py docker-compose.yml environment.sh nginx.conf projects redis.conf redis_socket SECRET_KEY [root@awx01 awx]# docker-compose ps Name Command State Ports ------------------------------------------------------------------------- awx_redis docker-entrypoint.sh /usr/ ... Up 6379/tcp awx_task tini -- /usr/bin/launch_aw ... Up 8052/tcp awx_web tini -- /bin/sh -c /usr/bi ... Up 0.0.0.0:80->8052/tcpAWXの各コンテナが完全に起動準備が整うと、以下の様なログを出すのでしばらく待つ。
[root@awx01 awx]# docker-compose logs -f : web_1 | RESULT 2 web_1 | OKREADY task_1 | RESULT 2 task_1 | OKREADYAWXの起動後の手直し
こんな感じでRedisの警告が出てるのでその対策 1 を実施する。
redis_1 | 1:M 18 Jun 2020 14:38:52.466 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.上記の警告がAWXインストーラでサポートしていないので手動でRedisサービスを変更する。
また、docker-composeのversionも3に変更(2ではsysctls 2 が使えないので)。AWXを停止
[root@awx01 awx]# docker-compose down Stopping awx_task ... done Stopping awx_web ... done Stopping awx_redis ... done Removing awx_task ... done Removing awx_web ... done Removing awx_redis ... done Removing network awx_default
/var/lib/awx/docker-compose.yml
を以下の様に変更version: '3' # ← ここを 2から3に services: : redis: : sysctls: # この2行を追加 net.core.somaxconn: '511' #補足
長時間稼働すると、AWXサービスから出力される各コンテナのログでDiskがいっぱい!なんて事にならないように、以下を参考に、syslogに出力するとか、ログローテートするなどの対策を行って下さい。
- Docker Composeへの設定方法
- そもそものDockerコンテナのlogging driversの説明
AWXを起動
[root@awx01 awx]# docker-compose up -d※実行後は、
docker-compose logs -f
で実行の様子を確認することブラウザで、
http://(ホストのIPアドレス)/
にアクセスすると下図の様にログイン画面が出てくるので、AWXのインストーラのInventoryで設定したadmin_user
とadmin_password
を使ってログインする。
FAQ:アップデートどないするの?
基本的にインストーラをイチから作成し直す(流用しない)
- データベースは外部のPostgreSQLにあるので、データベースをバックアップ
/root/awx/awx
にcloneしたインストーラをリネーム ※なんかあった時の切り戻し用docker-compose down
でAWXを停止/var/lib/awx
をリネーム ※なんかあった時の切り戻し用- いつもの通り再セットアップ ※Inventoryだけ、2でリネームしたやつを使い回す
アップデートする際の注意事項
- 投稿日:2020-06-28T09:38:33+09:00
dockerで複数のコンソールに入る
docker exec -it [Container name] /bin/bash
- 投稿日:2020-06-28T06:25:44+09:00
Remote ContainerでReactのDocker開発環境を構築
概要
- 過程より結果が大事だと3部と5部のラスボスが言っていたのでまず成果物を記載します。
- 開発環境は下記のリポジトリにあるのでお好きに使って下さい。
- react-docker-development-environment
- そのままpushをすると、私のリポジトリの内容が変更されてしまうので、pushとかは自分のリポジトリを作成して行って下さい。
- VSCodeの拡張機能は自分が普段開発に使用している物をインストールするように設定しております。他にも何かオススメがあれば教えてください
- 使用して気に入ったのなら☆を付けてくれると励みになります。
前提
- Docker
- いまさらだけどDockerに入門したので分かりやすくまとめてみた
- 自分はWSL2で環境構築しました
Remote-Container
- VSCode Remote Containerが良い
- この記事にDockerやRemote-Containerで環境構築することの良さが書かれてます
なぜDockerでReactの開発環境を作るのか
- プロジェクトでnodeのバージョンなどを固定できる
- ホストマシンにNodeを入れなくてOK
- プロジェクトメンバーが増えてもコンテナを開くだけで環境構築が完了
なぜRemote-ContainerでReactの開発環境を作るのか
- DockerだけだとVSCodeの拡張機能などを入れる手間がかかる。(プロジェクト配下の.vscodeに設定を書けば推奨の拡張機能として表示させることは可能だったはず)
- Remote-Containerならコンテナを開くときに拡張機能をインストールしてくれるので共有が楽
- VSCodeの設定もプロジェクト単位で統一可能。(フォーマッターなど)
- プロジェクトメンバーが増えてもコンテナを開くだけで環境構築が完了(超重要)
使い方
- react-docker-development-environmentを git clone
- VSCodeの拡張機能でRemote Containerを追加する
- VSCodeで Ctr + Shift + p と入力
- Remote-Containers: Open Folder in Container と入力
- プロジェクト配下のdockerという名前のフォルダを選択する(.devcontainer配下が展開される)
- 実際に開発環境として使用する場合、ssh-agentを有効にしないとPushできません
CreateReactApp
今回の環境はReactでTypeScriptを使用し、storybookの環境構築を済ませた環境になっております。
自分で環境構築を行う場合、以下の手順でできます。
- Nodeを使用可能なコンテナを起動
コンテナ内で以下のコマンドを実行
npm install -g create-react-app ## TypeScriptでReactのApplication構築を行う(テスト環境も配備) create-react-app sample --typescript cd sample # Reactのプロジェクトフォルダ配下で実行することでstorybookの環境構築を行う npx -p @storybook/cli sb init --type react_scripts実装した内容
実際に環境変数で使用している内容の解説をします。
Dockerfile# ベースとするDockerImage FROM node:13.12.0-slim WORKDIR /usr/app # パッケージの依存関係に関するファイルをホストからDocker内にコピー COPY package.json yarn.lock tsconfig.json ./ # yarn install する RUN yarn # yarn install 後、全ファイルをコピーすることで、パッケージ関連がコピーされ、キャッシュが効くようになり高速化 COPY . . CMD [ "yarn", "start" ]docker-compose.yaml# compose fileのフォーマットバージョン(バージョンによって使える記法が違う) version: '3.7' services: node: build: # 使用するDockerFileのDirectoryを指定 context: ../../ # 使用するDockerFileの名前を指定(Dockerfile.Nodeはdocker-compose.yamlと同じディレクトリにあるが、contextで2階層上を使用すると指定している、だからわざわざdocler/.devcontainer/ という風にしてDockerfile.Nodeを指定) dockerfile: docker/.devcontainer/Dockerfile.Node volumes: # ローカルのディレクトリが接続(マウント)する作業ディレクトリを指定(srcフォルダをusr/app/src にマウントしている) - ../../src:/usr/app/src # 外部に対して公開するポート番号 ports: - "3000:3000" # コンテナを起動させ続けるか管理するフラグ tty: truedevcontainer.json{ "name": "Existing Docker Compose (Extend)", "dockerComposeFile": [ "docker-compose.yml" ], "service": "node", "workspaceFolder": "/usr/app/", // VSCodeのTerminalが開くディレクトリを設定 "settings": { "terminal.integrated.shell.linux": null, "files.trimTrailingWhitespace": true, // ファイル保存時に行末の空白自動削除 "editor.formatOnSave": true // ファイル保存時に自動フォーマットが実行される }, // Remote-Container で起動した際にVSCodeの拡張機能をインストール "extensions": ["eamodio.gitlens","chakrounanas.turbo-console-log","visualstudioexptteam.vscodeintellicode","esbenp.prettier-vscode","dbaeumer.vscode-eslint","shardulm94.trailing-spaces","msjsdiag.debugger-for-chrome","christian-kohler.path-intellisense","usernamehw.errorlens","gizak.shortcuts","coenraads.bracket-pair-colorizer-2"], // Remote-Container で起動した際にgitをインストール "postCreateCommand": "apt-get update && apt-get install -y git", }苦戦した点
コンテナ内でホットリロードが効かない
Reactのプロジェクトフォルダ配下にenvファイルを配置することで解決
env// コンテナ内でホットリロードを有効にするための環境変数 CHOKIDAR_USEPOLLING=trueyarn start が遅い
- 一番苦労した点、コンテナ内だと5分かかることもありました。(ローカルだと10秒で終わる)
- 原因はyarn がキャッシュされておらず一々node_modulesを作成してたから
- 下記の記事の内容で解決しました
- Docker for Macは遅いらしいのでMacの方は注意が必要らしいです。
経緯
- Excelや社内Wikiなどで書かれた環境構築資料の通りにやってもエラーが出て環境構築できない
- 結果、環境構築だけで時間が消える
- プロジェクトメンバーが増える度に同じ時間が無駄になる
- 溜まっていく疲労と虚無感
- Remote-Containerなら秒で終わる!
- これからはコンテナが入っていれば環境構築が秒で終わる
- みんな幸せ
参考資料
Docker Composeの仕様について混乱しがちな箇所を整理した
- 投稿日:2020-06-28T00:51:10+09:00
express mysql docker-compose Error: connect ECONNREFUSED
解決策
const express = require('express') const app = express() var mysql = require('mysql'); var connection = mysql.createConnection({ host : 'mysql', // localhostは間違い, 0.0.0.0は間違い port : 3306, user : 'root', password : 'password', database : 'testdb' });対象
docker-composeでnodejs(express), mysqlを立ち上げて接続しようとしてエラーが出た人。
自分の場合、hostを修正した場合に成功しました。
user, password, databaseは各自確認してください。
- 投稿日:2020-06-28T00:42:49+09:00
はじめてのDockerでRails開発環境構築 [NGINX + Rails 5 (puma) + PostgreSQL]
はじめてのDockerでRails開発環境構築 [NGINX + Rails 5 (puma) + PostgreSQL]
それなりに時間を書けて取り組んだので改善点等コメントいただけると嬉しいです
GitHubにコードも上げてありますので、必要があれば公開いたします同様にコメントくださいなぜやるか
- 今後AWSのEC2上にNGINX + puma (Rails) + PostgreSQLの環境でアプリをデプロイしたい
- 開発環境も同じ構成でやりたい
- 実務での開発を意識してDockerを使ってローカル開発環境を構築したい
- Railsチュートリアルでお世話になったAWS Cloud9ではなく、VS Codeを使いたい
何を得たか
- Dockerの基礎知識、概念
- 快適なローカル開発環境 (VSCode素敵)
- 初学者が開発環境構築までやると時間対効果よくない(丸一日かかりました...)
- ただし、一度構築してしまえば環境の再現は恐ろしく簡単、環境の共有という視点も納得(シェル書けばあっという間?)
- AWSデプロイもこのまま行けそう、という謎の自信
- 一次情報大事という気づき
- Railsチュートリアルの製作者たちが様々な工夫で環境構築のハードルを劇的に下げてくれていることへの感謝と、それ以上の柔軟性と実用性を提供してくれるDockerの素晴らしさ
結論
手順通りに進むと、表題のRails開発環境が手に入る、はずです
初学者がポートフォリオ作成のロードマップの中でDockerを導入するのであれば、
先人のお知恵を借りて、既存の開発環境を自分のローカル環境に取り入れるくらいの感覚のほうが良いかもしれない時間をかけてRailsチュートリアルに取り組める、かつ私のような物好きは
Dockerで環境構築から初めて、環境の差による不具合を敢えて乗り越えて行くのも粋かもしれない環境・スキル
- Mac OS (Mojave)
- Docker for Mac, Docker composeインストール済み
- Ruby 2.5
- Rails 5.2.4.3
- Nginx 1.15.8
- PostgreSQL
- Rails チュートリアル1周目、Docker初心者
参考
Docker公式docs: 基本的にこの流れを踏襲しています
Quickstart: Compose and Rails | Docker Documentationnginx公式docs: 設定例
Full Example Configuration | NGINXnginxほか設定例
nginxについてまとめ(設定編) - Qiitapumaの設定はこちらを参考
既存のRailsアプリのローカル開発環境をDockerの仮想環境に切り替える - りょ〜Blogボリュームマウントの構成はこちら
Docker + Rails + Puma + Nginx + MySQL - Qiita備忘録
ディレクトリ構成
(予め用意するもののみ記載)
sample_app ---- Dockerfile |-- Gemfile |-- Gemfile.lock |-- nginx ---- Dokerfile | |-- nginx.conf | |-- config ---- database.yml (後で自動生成) | |-- puma.rb (後で自動生成) | |-- environments --db.env (今回うまく使えてません) | |-- docker-compose.yml |-- entrypoint.shDockerfile (Ruby)作成
まずはruby用のDockerfileを用意
DockerfileFROM ruby:2.5 RUN apt-get update -qq && \ apt-get install -y nodejs \ postgresql-client RUN mkdir /myapp WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN bundle install #ホストからコンテナにコピー(ホスト側は相対パス) COPY . /myapp # Add a script to be executed every time the container starts. COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] #ソケット接続するのでいらないはず #EXPOSE 3000 # puma.sockを配置するディレクトリを作成 RUN mkdir -p tmp/sockets
Gemfile
(これはあとのrails new
コマンドで上書きされる)Gemfilesource 'https://rubygems.org' gem 'rails', '~>5'
Gemfile.lock
空のファイルで良いのでtouch
コマンドのみGemfile.locktouch Gemfile.lock
entrypoint.sh
entrypoint.sh#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /myapp/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"Dockerfile (NGINX)作成
次にnginx用のDockerファイルを用意
/nginx/DockerfileFROM nginx:1.15.8 # インクルード用のディレクトリ内を削除 RUN rm -f /etc/nginx/conf.d/* # Nginxの設定ファイルをコンテナにコピー ADD nginx.conf /etc/nginx/myapp.conf # ビルド完了後にNginxを起動 CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/myapp.conf上で呼び出される
nginx.conf
ファイル
(ログの部分はコメントアウトを外すと、ディレクトリが見つからないとエラーが出ます。どうしても解決できずコメントアウトのまま)/nginx/nginx.confuser root; worker_processes 1; events{ worker_connections 512; } # ソケット接続 http { upstream myapp{ server unix:///myapp/tmp/sockets/puma.sock; } server { # simple load balancing listen 80; server_name localhost; #ログを記録しようとするとエラーが生じます #root /myapp/public; #access_log logs/access.log; #error_log logs/error.log; location / { proxy_pass http://myapp; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; } } }Docker-composeを作成
これらのコンテナをうまくゴニョゴニョしてくれるという
docker-compose
docker-compose.yml
を以下のように記述
(env_file:
は書いているものの、うまく使えていないと思います)docker-compose.ymlversion: '3' services: app: build: . env_file: - ./environments/db.env command: bash -c "rm -f tmp/pids/server.pid && bundle exec puma -C config/puma.rb" volumes: - .:/myapp - public-data:/myapp/public - tmp-data:/myapp/tmp - log-data:/myapp/log depends_on: - db db: image: postgres env_file: - ./environments/db.env volumes: - ./tmp/db:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: password web: build: nginx volumes: - public-data:/myapp/public - tmp-data:/myapp/tmp ports: - "80:80" depends_on: - app volumes: public-data: tmp-data: log-data: db-data:Gemインストール
カレントディレクトリをDocker fileが配置されている場所に移動し
以下のdocker-compose run
コマンドでRailsを展開する
(この時Gemファイルが上書きされるはず)docker-compose run app rails new . --force --no-deps --database=postgresqlGemをインストールするために
docker-compose build
コマンドを実施
(Gemファイルおよび、Dockerファイルに変更がある場合のみ再度このコマンドが必要)Now that you’ve got a new Gemfile, you need to build the image again. (This, and changes to the Gemfile or the Dockerfile, should be the only times you’ll need to rebuild.)
(Docker 公式 docs)docker-compose build設定ファイルの修正
config/puma.rb
の中身を以下で置き換える/sample_app/config/puma.rbthreads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i threads threads_count, threads_count port ENV.fetch("PORT") { 3000 } environment ENV.fetch("RAILS_ENV") { "development" } plugin :tmp_restart app_root = File.expand_path("../..", __FILE__) bind "unix://#{app_root}/tmp/sockets/puma.sock" stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true
config/database.yml
の中身を以下で置き換える/sample_app/config/database.ymldefault: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_testコンテナを起動
docker-compose up
コマンドでアプリたちをを起動するdocker-compose up処理が止まっているように見えてもエラーが出ていなければサーバーが起動しているはずです、
docker-compose up -d
でターミナルの入力を継続できます
doker ps
で起動しているコンテナを確認すると
nginx(sample_app_web), puma(sample_app_app), DB(postgres)の3つが起動しているはず$ docker ps CONTAINER ID IMAGE COMMAND ... PORTS NAMES 7188a5bb9d3c sample_app_web "/bin/sh -c '/usr/sb…" ... 0.0.0.0:80->80/tcp sample_app_web_1 41759b7d078e sample_app_app "entrypoint.sh bash …" ... sample_app_app_1 1c81a75b5c22 postgres "docker-entrypoint.s…" ... 5432/tcp sample_app_db_1この時点で
localhost:80
にアクセスすると、
Railsのエラー画面、あともう少し
データベースがないよと言われるのでDBを作成する
docker-compose run app rake db:create完成
最後に
これRailsのコマンドはどうやって打つの?という残念なレベル...
docker-compose run app
に続けて記述するそうです
appはRailsが動いているコンテナですね$ docker-compose run app rails -v Starting sample_app_db_1 ... done Rails 5.2.4.3動いているコンテナを終了するのは
(これをやらないと次回起動時エラーが出る)$ docker-compose down再度起動するには
$ docker-compose up