奥さん、ご存知でした?今の流行りはコンテナらしいんですってよ!
隣の奥さんもやってますわよ!
コンテナがなんなのか知っている。 実はk8sも使える。なんならk8sのおかげでご飯を食べてるまである。
でもDocker環境がないから、どうも慣れない。
自宅環境にDocker導入は面倒くさいし必要なかったし…
重い腰を上げて、WindowsとArchLinuxにDocker環境を構築していこう。
今回の目標はWin10環境にDockerでNginx環境を作る。
まずはメインPCにDocker環境を入れる
メインPCはWindows10 64bit Education
Windows環境にDocker導入はまじでよく知らない
ここらへんを見ながら進めていこう
ref: Windows に Docker Desktop をインストール — Docker-docs-ja 19.03 ドキュメント
気になる記述がある。
Docker Desktop for Windows は、Mirosoft Windows 用の Docker コミュニティ 版です。
https://docs.docker.jp/docker-for-windows/install.html
Docker Desktop を Windows 10 Home にインストールする情報をお探しであれば、 Windows Home に Docker Desktop をインストール をご覧ください。
コミュニティ版とは有償版無償版の無償版らしい、JavaのSEとEEみたいなもんか
記述的にWindowsにはコミュニティ版(CE)しかなさそう(調べるのが面倒になった)
Hyper-Vの機能を使うので、Pro以上が必要
HomeでもWSL2を使って導入できるよ!と別途案内を出している。優しい
Docker HubでDocker Desktop Installer.exeを使ってインスコする
なんでもチェック入れた状態でOK押してえ
Install required Windows components for WSL2
の意味
直訳では、必要なWSL2用のWindowsコンポーネントをインストールする
わかる
このメインPCにはWSL2が入ってない
どうもWSL2への移行が必要かもしれない
この際だからやっておこう
WSL1を使い続ける理由もない
WSL1からWSL2へ移動
ここを参考に1から2へ移行する
ref: WSL1からWSL2への移行
まずは現状の確認とWSL2用設定の有効化
・Windowsのビルドが18362以上か確認
・「Windowsの設定→アプリ→オプション機能→Windowsのその他の機能」から仮想マシンプラットフォームを有効化
(もしくはPowerShellから有効化)
→必要であれば再起動する
cmd> ver Microsoft Windows [Version 10.0.19042.804] →19042なのでWSL2の必要条件はクリア →管理者権限でWSLの機能を有効化する cmd> sudo powershell PS> dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart →アプリからでも設定できるが、キーボードだけで完結できたので、こちらで
正直、WSL1とかが流行ってたときは、この辺の仮想化技術をONにするとVMwareが動かなくなったり、OFFにするとBluestackとかが動かなかったりですごく嫌な思いをしていた。
俺は整理できない人間なので、再起動はしたくないマンなんだ
しれっとWindowsでsudoコマンドを利用しているが、これはすごく便利だから絶対いれたほうが良い
ref: Windowsでsudoしたい – Qiita
とりあえず再起動
この時気づいたがuptime 19daysとか出てて笑った
再起動したらLinuxカーネル更新パッケージをインスコする
以下のページの手順4にLinuxカーネル更新の.msiがある
ref: 手順 4 – Linux カーネル更新プログラム パッケージをダウンロードする
→wsl_update_x64.msiが動く。一瞬で完了した。
wslのデフォルトversionを2にして、wslで動くlinuxもwsl2で動くようにする
cmd> sudo cmd →一応管理者権限のcmdで作業 cmd> wsl --set-default-version 2 WSL 2 との主な違いについては、https://aka.ms/wsl2 を参照してください →get-default-versionみたいなコマンドがなかったので、結構迷った wslで動くLinuxのversionを確認 cmd> wsl --list -v NAME STATE VERSION * Ubuntu Stopped 1 →Ubuntu がWSL1で動く様になっている、これを2にする cmd> wsl --set-version Ubuntu 2 変換中です。この処理には数分かかることがあります... WSL 2 との主な違いについては、https://aka.ms/wsl2 を参照してください 変換が完了しました。 →ちょっと時間がかかる cmd> wsl -l -v NAME STATE VERSION * Ubuntu Stopped 2 →WSL2になった
WSL2ならではなテスト出力があれば実際に動かしてテスト出来たが、ここでは面倒なのでdockerを入れることが主目的なのでほったらかす。
Dockerのインストーラに戻って作業
OK押して、インストール
You must log out of Windows to complete installation
→再起動まではしなくてもいい、ログアウトとログインだけが挟まる
Docker on Windowsが始まる
いきなりチュートリアルが始まった
いいだろう
k8sでよく見るコマンドだ
コンテナでgitを動かして、コンテナからローカルにファイルコピーをするようだ
正直、まずaplineのイメージをDLする必要があるはずなので、そこだけ動かしておく
PS> docker run --name test alpine →alpine:latestをDLして動かす実行文が出ていたが、コピペミスして記事に持ってこれなかった PS> docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 79d3535dced6 alpine "/bin/sh" 53 seconds ago Exited (0) 51 seconds ago test →ちゃんとalpineを持ってきて動かせているようだ PS> docker rm test →お掃除
従ってコマンドをやる
というか、画面左に出ている青いボタンを押したらpowershellで勝手に実行された
焦って、ディレクトリを変えたりした
PS> docker run --name repo alpine/git clone https://github.com/docker/getting-started.git PS> docker cp repo:/git/getting-started PS> start . →入れてほしくないとこに入れちゃったのでエクスプローラーで移動させる PS> cd unko/docker →docker用ディレクトリも用意したので、そこで PS> docker build -t docker101tutorial . →getting-startにはdocker用イメージが含まれている
Dockerfileをちょっと見てみる
大まかにはこう # pythonのモジュールをインストール FROM python:alpine AS base RUN pip install -r requirements.txt # Nodejsのモジュールをインストール FROM node:12-alpine AS app-base RUN yarn install # Nodejsのモジュールをzip化 FROM app-base AS app-zip-creator RUN zip -r /app.zip /app # ポート8000でmkdocs鯖を実行 # mkdocsはpythonで動くmarkdown形式のサイトジェネレータ FROM base AS dev CMD ["mkdocs", "serve", "-a", "0.0.0.0:8000"] # mkdocsで静的サイトデータを作成 FROM base AS build RUN mkdocs build # Nginxを動かす FROM nginx:alpine COPY --from=app-zip-creator /app.zip /usr/share/nginx/html/assets/app.zip COPY --from=build /app/site /usr/share/nginx/html
要はチュートリアルに含まれるマークダウンのサイトをmkdocsやらで動かして、それをnginxで見るような感じだろう
何度も言っていきたいが、俺は今まで雰囲気でDockerを使っている。Dockerに使われているミドルウェアには詳しくても、Dockerは詳しくない。雰囲気で読んでいる
俺もDockerに使われているので、理解するための環境構築だ
出来上がったDockerイメージを見る
PS> docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE docker101tutorial latest 5714b8ce5266 29 minutes ago 27.9MB alpine/git latest a939554ad0d0 2 weeks ago 25.1MB alpine latest 28f6e2705743 2 weeks ago 5.61MB →docker101tutorialのイメージが出来ている。容量も軽いしいいね
コンテナをバックグラウンドで実行して、コンテナのポート80をローカルのポートに割当し、実行
PS> docker run -d -p 12340:80 --name docker-tutorial docker101tutorial →チュートリアルは80に割り当てだったが、メインPCで80はすでに使っている(はず)なので、適当なポートに
このセキュリティの警告、ネットワーク関係で初回実行時に聞いてくるけど、初回以降は出てこないし、
一回キャンセルした後、もう一度開いたり、設定を変更するときはどうするんだろうか
すぐ話が逸れる
Nginxで接続待受されているはずなので、ブラウザでアクセスしてみる
localhostv4はSystem32/driver/etc/hostsをいじって IPv4のlocalhostと明記したやつ
http://localhostv4:12340/
OK!
とりあえずdockerは動いた
後はチュートリアルの掃除
PS> docker ps →docker-tutorialが動いているのを確認 PS> docker stop docker-tutorial PS> docker rm docker-tutorial PS> docker ps -a →ログ確認用等々のためのコンテナの残りものも無くなっていることを確認 stopせず直接rmとか出来ないのかな?(--rmでrunするのは除く)
チュートリアルは終わったし、最低限のラインは終わったでしょう。。
このdocker101tutorialイメージの中身をちょっと見てみる
PS> docker run --rm --name test -it docker101tutorial /bin/sh / # cat /etc/nginx/nginx.conf / # cat /etc/nginx/conf.d/default.conf →普通のnginx.confとdefault.confだった / # ls /usr/share/nginx/html; 404.html assets fonts index.html sitemap.xml tutorial 50x.html css images search sitemap.xml.gz →docsで作られたであろうファイル群が入っている / # cat /proc/cpuinfo (抜粋) model name : Intel(R) Core(TM) i7-6800K CPU @ 3.40GHz →hostPCの情報を持ってきているな、dockerってそういうものなのか / # cat /proc/meminfo MemTotal: 26144932 kB VmallocTotal: 34359738367 kB →26GB程度のメモリが使える? →vmmemというWSL2プロセスが3.5G程度メモリを専有していたがdockerが使っているんだろうか / # cat /etc/os-release NAME="Alpine Linux" →AlpineはAlpineだった
予想通りというかなんというか、、
後は好きにNginxだけのコンテナイメージを作成していく
vmmemについてちょっと気になったので cmd>wsl -l -v NAME STATE VERSION * Ubuntu Running 2 docker-desktop Running 2 docker-desktop-data Running 2 →確かにwslにdocker用が出来ている。 wslからリソースを引っ張ってきているっぽい、のかな?
Nginxだけのイメージ
Nginxだけのイメージと言ったが、正確にはチョットチガウ
Nginxだけのイメージだが、test用のTOPページと、nginx.confをいじりやすいように作りたい
confディレクトリとhtmlディレクトリを作って、それぞれ/etc/nginx/にコピー、/usr/share/nginx/htmlにコピーするようにしよう
Nginxの設定ファイル
nginx.confを1から書くのは面倒。
ちょうどnginxをそのまま起動したら初期設定ファイルが入っているはずなので、dockerから持ってくる
これはチュートリアルでやったことなので、特に説明はいらないだろう…
俺は雰囲気でdockerをやっている
test_nginxでnginxを実行する cmd> docker run -d --rm --name test_nginx nginx:alpine →nginx:alpineでdockerhubにある公式nginxを実行 →-dでバックグラウンドで実行、--rmで止めたときに自動削除 nginxの設定ファイルをちょっとshellで見てみる cmd> docker exec -it test_nginx sh →-itでインタラクティブなttyを割り当ててshを実行する →alpineはbashがないようだ(zshはあったりなかったりするっぽいが) 標準の場所に標準のファイル郡があるか見る / # ls /etc/nginx conf.d fastcgi_params koi-win modules scgi_params win-utf fastcgi.conf koi-utf mime.types nginx.conf uwsgi_params →よく見るファイル群 ちょっと覗く / # head -5 /etc/nginx/nginx.conf user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; →よく見るやつだ Ctrl+Dでlogout(職場でもCtrl+Dだったりしっかりlogout or exitを入力していたり、どれがいいのだろうか) / # ^D cmd> ローカルに持ってくる cmd> cd ../tiny-nginx cmd> docker cp test_nginx:/etc/nginx/nginx.conf ./ cmd> docker cp test_nginx:/etc/nginx/conf.d ./ →ディレクトリごとcpもいけた cmd> dir (抜粋) -a---- 2021/02/17 1:25 646 nginx.conf da---- 2021/03/11 7:07 conf.d →持ってこれたみたいだ →cpは基本unixのcp -aと同じらしい
dockerでnginx:alpineだとかnginx:latestだとかを少し理解したい
公式はまだ見ていないのだが、これだけでdockerhub公式で公開されているイメージファイル落とせるらしい
イメージファイルを探す場合はこのコマンド$ docker search nginx
雰囲気からして、公式イメージはnginx:latest
、unkoさんの作ったカスタムイメージ(非公式)はunko/nginx:latest
だろう
ref: Dockerイメージの理解を目指すチュートリアル – Qiita
この時気づいたのだが、alpineだけのイメージを先にDLしておくのはpullコマンドでできるらしい$ docker pull alpine
k8sでもこのコマンドが使えるようだ。知らなかった。こういうことに気付けるのはありがたい。
ちなみに、cpコマンドでのパスは
コンテナに対しては必ず/(root) からの絶対パス
ローカルに対しては現在の作業パスからの相対パス
になるらしい
コンテナの/(root)指定はオプションで/etc/nginx
はetc/nginx
と同じらしい
ref: cp — Docker-docs-ja 19.03 ドキュメント
こういうときだけ公式ドキュメントを見るマン
confフォルダを作ってその中でnignxのconfを触る
cmd> mkdir conf cmd> cd conf
user nginx; worker_processes 2; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; multi_accept on; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; server_tokens off; keepalive_timeout 90; server { listen 80 default_server; root /usr/share/nginx/html; index index.html index.htm; location / { } location /server_status { stub_status; } } }
雑だがこんなもんだろう
nginxがローカルにない(cmdですぐ使える場所にはない)ので、dockerに持っていってテストする
cmd> docker cp ./nginx.conf test_nginx:etc/nginx/nginx.test.conf cmd> docker exec -it test_nginx sh / # cd /etc/nginx /etc/nginx # mv nginx.conf nginx.conf.old /etc/nginx # mv nginx.test.conf nginx.conf /etc/nginx # nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful nginxをreload /etc/nginx # nginx -s reload →最初普通のnginxと同じようにsystemctlとかinit.dとかかな?とか考えてたけど、このコマンドでOKだった →もちろん、コンテナをreloadしたりするのが一般的だろうが、ここはconfファイルのチェックをしたいのみなので、nginxをreloadした /etc/nginx # wget localhost -q -O - <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> /etc/nginx # wget localhost/server_status -q -O - Active connections: 1 server accepts handled requests 5 5 5 Reading: 0 Writing: 1 Waiting: 0 →ちゃんとstub_statusの設定が効いていた。やりたいこととしてはOKだろう
nginxのstub_statusの挙動を見たいため、stub_statusをonにした設定ファイルをテスト
curlがなかったので、wget
ここで少し気になったのだが、stub_status関係
今、自宅鯖で動いている殆どのnginxはstub_status on;
になっている。
しかし、ドキュメントを見ると、
In versions prior to 1.7.5, the directive syntax required an arbitrary argument, for example, “
Module ngx_http_stub_status_modulestub_status on
”.
古い(1.7.5より前)のnginxはstub_status on;
だが、現在はstub_status;
のみで良いらしい
localhost/server_status でContent-Lengthを見ると100らしいので、だいたい100バイトと記憶 (メモ用です)
では、この設定ファイルを基準にDockerfileを書いていく
index.htmlは特記いいでしょう…
<!doctype html> <html> <body> <h1>Hello Nginx on Docker!</h1> work on dokcer </body> </html>
これでちょうど100bytes
ちなみに改行は\r\n
index.htmlで保存
Nginx のDockerfile記述
まずは雰囲気でDockerfileを書く。書いた。
特に問題なく動いた
なにがスタートアップで動くか自分で書くことなく動くというのは違和感がある
├Dockerfile
├index.html
└conf/
└nginx.conf
# and use a nginx image to serve the content FROM nginx:alpine COPY conf/nginx.conf /etc/nginx/ COPY index.html /usr/share/nginx/html/
ビルドして動かしてみる
cmd> docker build -t tiny-nginx . cmd> docker image ls tiny-nginx latest 92871f963da3 18 seconds ago 22.6MB cmd> docker run -it --rm --name tiny -p 12340:80 tiny-nginx sh / # cat /usr/share/nginx/html/index.html <!doctype html> <html> <body> <h1>Hello Nginx on Docker!</h1> work on dokcer </body> </html> →ちゃんと入れたindex.htmlになっている
特に明記しなかったが、今まで調べる上で docker-compose.yml とdockerfileでの実行順の話を何度か見た
実際、コンテナ内でdocker-entrypoint.shが動いているのを見た
どうやらdockerfileは起動するまえに実施する内容で、docker-compose.ymlはコンテナが動いてから何をスタートアップに動かすかというもののようだ
つまり、dockerfileに書いた内容、オフィシャルイメージのnginxに含まれるentrypoint.shでnginxがスタートして、docker-compose.ymlで curl localhostみたいなことができるんだろうと予想
これは次回調べよう
ブラウザでアクセスしてみる
http://localhostv4:12340/
→このページは動作していません
shで入っているとダメなのか?コンテナ内のローカルでもダメでした
しかし、docker ps -aで見てみるとちゃんと動いているし、ポートマッピングも出来ている
cmd> docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2309578fa395 tiny-nginx "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:12340->80/tcp tiny →COMMAND行にdocker-entrypoint.shと書いてあるから、てっきりスタートアップ等は動いているものだと思っていた
Docker コマンドラインでのオプション コマンド を取り消します。
Docker run リファレンス — Docker-docs-ja 19.03 ドキュメント #cmd
$ docker run [オプション] イメージ[:タグ|@DIGEST] [コマンド] [引数…]
このコマンドは様々なオプションを指定します。 イメージ の作者が Dockerfile の CMD 命令を使い、デフォルトの コマンド を既に設定している場合があるためです。作業者(イメージからコンテナを実行する人)は、 CMD 命令を上書きして新しい コマンド を実行します。
イメージに ENTRYPOINT も指定されていれば、 CMD や コマンド は ENTRYPOINT に対する引数となります。
どうやらentrypointに指定されているnginx コマンドがsh指定によって上書きされて実行されていないようだ
ざっと調べたがentrypointに指定コマンドを追記して実行というのはないようだ
execで入るしかなさそう
試しにnginxを手動スタート
cmd> docker run -it --rm --name tiny -p 12340:80 tiny-nginx sh / # wget localhost -O - Connecting to localhost (127.0.0.1:80) wget: can't connect to remote host (127.0.0.1): Connection refused / # nginx / # wget localhost -O - Connecting to localhost (127.0.0.1:80) 127.0.0.1 - - [11/Mar/2021:22:37:20 +0000] "GET / HTTP/1.1" 200 100 "-" "Wget" "-" writing to stdout <!doctype html> <html> <body> <h1>Hello Nginx on Docker!</h1> work on dokcer </body> </html> - 100% |***********************************************************************| 100 0:00:00 ETA written to stdout
ブラウザでもアクセスできた
話が横に逸れたが、Dockerfileで指定したconfはちゃんと指定したものが動いているか
もちろん、上記のように手動でnginxを起動させた場合ではない
cmd> docker run -d --rm --name tiny -p 12340:80 tiny-nginx
ブラウザでアクセス
http://localhostv4:12340/
→OK
http://localhostv4:12340/server_status
Active connections: 2 server accepts handled requests 2 2 4 Reading: 0 Writing: 1 Waiting: 1
OKだ
かなり長くなってしまったような気がするが、やりたい最小のnginxコンテナは出来たようだ
–rm指定しているのでstopでコンテナが消えることも確認できた
php-fpmだけのコンテナに向けて
これは次回以降でのブログの主題になるだろうが、ちょっと調査したのでメモ的に。
もちろん、php-fpmとnginxを一つのコンテナに同梱させるというのもいいだろう
unixソケットで通信できるし、何より管理が楽だ
だが、phpだけnginxコンテナに同梱させるというのも変な話だ。
なぜなら、バックエンドはphpだけという話でもなく、今どきはpythonやrubyなんかにやらせることが多いだろう
APIバックエンドをKotlinでやっているなんて話もに挟んだことがある。
となると、nginxだけのコンテナ、各APIサーバのコンテナ、と分けたほうが運用は楽だろう。
多分k8sで動かしてPod単位で管理していきそうだし
php-fpmでのイメージは公式イメージにないようだ。
ちなみに公式イメージがあるかどうかは–filter にて is-official=true を指定すればOK
ref: search — Docker-docs-ja 19.03 ドキュメント #フィルタリング
cmd> docker search php-fpm --filter is-official=true NAME DESCRIPTION STARS OFFICIAL AUTOMATED cmd> →リストで出てこないので、無いようだ
調べたところ、php:<version>-fpmでイメージが作られているらしい。
ref: php – hub.docker.com
ややこしい…
phpのver8.0.xのfpmイメージを探す
この記事を書いた時点での最新版はphpは8.0.3が最新だった。(2021/03/15 07:30 JST)
上記phpの参照リンクにはphp:<version>-fpmで入れられるらしいが、サポートタグには 8.0.3-fpm-alpine
とある。
どっちだ?
試しに入れてみよう
cmd> docker run -it --rm php:8.0.3-fpm sh 8.0.3-fpm: Pulling from library/php ...(省略) 8.0.3-fpm: Pulling from library/php # ls # ls # ls -al total 8 drwxrwxrwx 2 www-data www-data 4096 Mar 13 02:16 . drwxr-xr-x 3 root root 4096 Mar 13 02:16 .. # cd / # ls -al total 72 -rwxr-xr-x 1 root root 0 Mar 14 22:52 .dockerenv drwxr-xr-x 1 root root 4096 Mar 13 02:16 bin drwxr-xr-x 2 root root 4096 Jan 30 17:37 boot ...(省略) # echo $PS1 # # →これは気持ち悪いが、まあ動いていることは確認できた # cat /etc/os-release PRETTY_NAME="Debian GNU/Linux 10 (buster)" NAME="Debian GNU/Linux" VERSION_ID="10" VERSION="10 (buster)" VERSION_CODENAME=buster ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/"
上のdockerhubのphpに対応イメージの一覧があるが、指定なしだとbusterが入るようだ。
busterとはなんだとは思ったが、os-releaseを見たところDebianが動いているらしい。
alpineと並列で書いてあったので、busterはrebian系のdocker特化か何かという理解(今度調べよう)
ちなみに、php:latest-fpmはないみたい
cmd> docker run -it --rm php:latest-fpm sh Unable to find image 'php:latest-fpm' locally docker: Error response from daemon: manifest for php:latest-fpm not found: manifest unknown: manifest unknown. See 'docker run --help'.
phpなんかは容易に変更するものではないとは知っているが、これはこれでちょっと面倒くさい
マイナーバージョンの変更も追っていかないといけない
個人的にはメジャーバージョンアップは慎重にしなければ行けないが、マイナーバージョンはガンガンアップデートしたほうが良いと思っている
そのためのバージョン番号なのだから
まとめ
win10proだとdockerは簡単に入った。
ブログにまとめられなかったがHomeだとwsl2をしっかり入れられれば、こちらも比較的簡単に入った。
ありがとうWSL
dockerfileについて調べつつ、コンテナを作っていこう
cmakeをやっているようで、簡単だろうが面倒くさい。そんな予想がこれからの意欲を削っていく気持ちがある。
cmdで作業するとCtrl+wで単語削除みたいなショートカットが出来ないのがクソ面倒くさい
多分他のキーに割当されているんだろうが、調べる気力もなかった。
PowerShell?知らん、そんなもの