tag:crieit.net,2005:https://crieit.net/tags/Docker/feed 「Docker」の記事 - Crieit Crieitでタグ「Docker」に投稿された最近の記事 2022-12-29T16:47:37+09:00 https://crieit.net/tags/Docker/feed tag:crieit.net,2005:PublicArticle/18357 2022-12-29T16:47:37+09:00 2022-12-29T16:47:37+09:00 https://crieit.net/posts/Docker-run-bash-ash Docker run の起動時に任意コードを実行後 bash や ash を終了しない <p>この記事は、 <a target="_blank" rel="nofollow noopener" href="https://qiita.com/advent-calendar/2022/docker">Docker Advent Calendar 2022</a> の 23日目の記事だ。<br /> 空いていたので埋めちゃうよ。</p> <p>この記事では、 bash や ash で任意のコードの実行後、ターミナルを終了せずに入力待ちにする方法について紹介する。<br /> 特に、 <code>docker run</code> の実行後に、その環境を維持したまま入力待ちにすることを考える。</p> <p>例えば、 Windows コマンドプロンプトや PowerShell であれば、 <code>CMD /K ***</code> オプションや、 <code>-NoExit -Command ***</code> オプションで実現できるような内容だ。</p> <p>本来なら、 docker build にてその任意コードの実行後の内容をイメージにするべきだが、 わざわざ build するまでもないとか、 build できない事情などもあるかもしれない。</p> <p>ということで、 bash の場合と、 alpine などで使われる BusyBox ash それぞれについて、 <code>docker run</code> 実行時に任意コード実行後、ターミナルの入力待ちにする方法を紹介する。</p> <h2 id="bash の場合"><a href="#bash+%E3%81%AE%E5%A0%B4%E5%90%88">bash の場合</a></h2> <p>bash の場合、 <code>--rcfile</code> オプションにて、起動時に実行するコマンドを指定できる。</p> <p>ただし、 <code>--rcfile</code> はファイルを指定する必要があるため、 替わりに<strong>プロセス置換</strong>で実行コードを与えてやる方法をとる。</p> <pre><code class="console">user@hostmachine:~$ docker run --rm -it debian:bullseye bash -c "bash --rcfile <(echo 'ls && export '\''FOO=B A R'\'' && MY_TIME=\$(date)')" bin dev home lib64 mnt proc run srv tmp var boot etc lib media opt root sbin sys usr root@container:/# echo $FOO : $MY_TIME B A R : Thu Dec 22 15:00:00 UTC 2022 root@container:/# </code></pre> <p>プロセス置換はコンテナ内で実行される必要があるため、一旦 <code>bash -c</code> にてコンテナ内で bash 実行させ、その中で改めて <code>--rcfile</code> オプションを指定した bash を起動する流れとなる。</p> <p>実際に実行したいコマンドは、 echo で文字列として書き出す。<br /> 上記例では、 <code>ls && export 'FOO=B A R' && MY_TIME=$(date)</code> と言う文字列を echo させている。</p> <p>引用符が二重三重になっていて、エスケープが非常に難しくなっているので注意。</p> <h2 id="BusyBox ash"><a href="#BusyBox+ash">BusyBox ash</a></h2> <p>alpine 3.15 以降に含まれる BusyBox の ash であれば、意外にもプロセス置換が使える。</p> <p>しかし、 <code>--rcfile</code> に相当するオプションは残念ながら無い。<br /> 替わりに、 ash には <code>ENV</code> という環境変数に記載されたファイルを ash 起動時に実行する機能がある。</p> <p>これを使おう。</p> <pre><code class="console">user@hostmachine:~$ docker run --rm -it alpine:3.15 ash -c "ash -c 'export ENV=\$1;ash' -s <(echo 'ls && export '\''FOO=B A R'\'' && MY_TIME=\$(date)')" bin etc lib mnt proc run srv tmp var dev home media opt root sbin sys usr / # echo $FOO : $MY_TIME B A R : Thu Dec 22 15:00:00 UTC 2022 / # </code></pre> <p><code>ash</code> の <code>-c</code> のコマンドに対して引数を与える <code>-s</code> オプションを使ってプロセス置換のファイルを与え、 それを <code>$1</code> 経由で <code>ENV</code> 環境変数にセット。 その状態で再度 ash を起動させれば、 bash と同様のことが行える。</p> <p>ENV 環境変数に直接プロセス置換のファイルを指定せず、わざわざ一旦引数を経由させているのは、 入力を受け付ける ash プロセスが動いている間、 プロセス置換のファイルにアクセス可能にする必要があるためだ。<br /> 例えば、 <code>export ENV=<(echo 'command');ash</code> と実行しても、 ash 実行の段階ではプロセス置換のファイルが閉じられているので、コマンドは実行されない。</p> <h2 id="もうちょっと複雑な例"><a href="#%E3%82%82%E3%81%86%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E8%A4%87%E9%9B%91%E3%81%AA%E4%BE%8B">もうちょっと複雑な例</a></h2> <p>起動時に apt パッケージマネージャーのリポジトリを書き換える方法(Ubuntu):</p> <pre><code>docker run --rm -it ubuntu:22.04 bash -c "bash --rcfile <(echo 'sed -i -E '\''s%^(deb(-src|)\s+)https?://(archive|security)\.ubuntu\.com/ubuntu/%\1http://srv2.ftp.ne.jp/Linux/packages/ubuntu/archive/%'\'' /etc/apt/sources.list && apt update && FooBar=`date -uIs`')" </code></pre> <p>起動時に apk パッケージマネージャーのリポジトリを書き換える方法(Alpine):</p> <pre><code>docker run --rm -it alpine:3.15 ash -c "ash -c 'export ENV=\$1;ash' -s <(echo 'sed -i -E '\''s%^https?://dl-cdn\.alpinelinux\.org/alpine/%https://ftp.udx.icscoe.jp/Linux/alpine/%'\'' /etc/apk/repositories && apk update && FooBar=`date -uIs`')" </code></pre> <p>参考: <a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/74094552/how-not-to-terminate-after-carried-out-commands-in-bash">https://stackoverflow.com/questions/74094552/how-not-to-terminate-after-carried-out-commands-in-bash</a></p> advanceboy tag:crieit.net,2005:PublicArticle/18307 2022-10-17T01:50:47+09:00 2022-12-03T04:13:34+09:00 https://crieit.net/posts/Docker-634c36677647a Docker練習メモ <p>Docklerのダウンロード</p> <pre><code># yum -y install docker # 1.Dockerコマンドの基礎 ## 1-1.imageの管理 ### imageのダウンロード </code></pre> <p>[opc@publicpc1 ~]$ docker pull nginx<br /> Using default tag: latest<br /> latest: Pulling from library/nginx<br /> 214ca5fb9032: Pull complete<br /> f0156b83954c: Pull complete<br /> 5c4340f87b72: Pull complete<br /> 9de84a6a72f5: Pull complete<br /> 63f91b232fe3: Pull complete<br /> 860d24db679a: Pull complete<br /> Digest: sha256:2c72b42c3679c1c819d46296c4e79e69b2616fa28bea92e61d358980e18c9751<br /> Status: Downloaded newer image for nginx:latest<br /> docker.io/library/nginx:latest</p> <pre><code><br />### ローカルにあるdockerイメージの一覧を表示 </code></pre> <p>[opc@publicpc1 ~]$ docker images<br /> REPOSITORY TAG IMAGE ID CREATED SIZE<br /> nginx latest 7425d3a7c478 4 days ago 141MB<br /> hello-world latest feb5d9fea6a5 7 months ago 13.3kB<br /> ```</p> <pre><code>[opc@publicpc1 ~]$ docker history nginx IMAGE CREATED CREATED BY SIZE COMMENT 7425d3a7c478 4 days ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B 4 days ago /bin/sh -c #(nop) STOPSIGNAL SIGQUIT 0B 4 days ago /bin/sh -c #(nop) EXPOSE 80 0B 4 days ago /bin/sh -c #(nop) ENTRYPOINT ["/docker-entr… 0B 4 days ago /bin/sh -c #(nop) COPY file:09a214a3e07c919a… 4.61kB 4 days ago /bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7… 1.04kB 4 days ago /bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b0… 1.96kB 4 days ago /bin/sh -c #(nop) COPY file:65504f71f5855ca0… 1.2kB 4 days ago /bin/sh -c set -x && addgroup --system -… 61.1MB 4 days ago /bin/sh -c #(nop) ENV PKG_RELEASE=1~bullseye 0B 4 days ago /bin/sh -c #(nop) ENV NJS_VERSION=0.7.2 0B 4 days ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.21.6 0B 4 days ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B 4 days ago /bin/sh -c #(nop) CMD ["bash"] 0B 4 days ago /bin/sh -c #(nop) ADD file:4a0bb88956083aa56… 80.4MB </code></pre> <h3 id="ローカルにあるイメージの削除"><a href="#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AB%E3%81%82%E3%82%8B%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%AE%E5%89%8A%E9%99%A4">ローカルにあるイメージの削除</a></h3> <pre><code>[opc@publicpc1 ~]$ docker rmi nginx Untagged: nginx:latest Untagged: nginx@sha256:2c72b42c3679c1c819d46296c4e79e69b2616fa28bea92e61d358980e18c9751 Deleted: sha256:7425d3a7c478efbeb75f0937060117343a9a510f72f5f7ad9f14b1501a36940c Deleted: sha256:c263493a5dc62ebefab0486e0019affdd5f663aad79cb5cf67f1ef21b2aba3c4 Deleted: sha256:c0a19d1cdcd1bebfd81765ad4971708d177b06a1cb0eaf0bb721745fd8d7f055 Deleted: sha256:c953b0422ec13844d8700eaf0159a800fba90fa6321f6ce1adc57f7f8566a0f1 Deleted: sha256:f121c2b08c669e9bb8e37bdc4ca0f32047d1b37f3ca3e3e302d9d1350301ad0b Deleted: sha256:138bdf299d05c844ac8833a0a2227499678214d264c3f6dde62cd4c9fb134932 Deleted: sha256:fd95118eade99a75b949f634a0994e0f0732ff18c2573fabdfc8d4f95b092f0e </code></pre> <h2 id="1-2.コンテナの操作"><a href="#1-2.%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E6%93%8D%E4%BD%9C">1-2.コンテナの操作</a></h2> <h3 id="dockerの起動"><a href="#docker%E3%81%AE%E8%B5%B7%E5%8B%95">dockerの起動</a></h3> <p>docker run <イメージ名> [:タグ名] コマンド</p> <pre><code># docker run centos:6 cat /etc/redhat-release Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg. CentOS release 6.10 (Final) </code></pre> <p>そのほかにも、nginxというコンテナ名で起動。その場合は「--name」オプションをつける。</p> <pre><code>[opc@publicpc1 ~]$ docker run --publish 80:80 --name nginx nginx #--publishは「-p」でもよい。 #80:80は、ホスト側のポートが80で、コンテナ側が80ということ #host側はなんでもよい #nginはデフォルトで80番ポートをオープンにしている </code></pre> <p>バックグラウンドで起動したい場合は以下<br /> <code>detach</code>することでターミナルからコンテナプロセスから切断することでアウトプットが返ってこなくなる。</p> <pre><code>docker run -p 80:80 --detach nginx </code></pre> <h3 id="起動中のコンテナ一覧"><a href="#%E8%B5%B7%E5%8B%95%E4%B8%AD%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E4%B8%80%E8%A6%A7">起動中のコンテナ一覧</a></h3> <pre><code>[opc@publicpc1 ~]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES af082867c083 nginx "/docker-entrypoint.…" 33 seconds ago Up 31 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx </code></pre> <p>動作終了したコンテナも含めて表示する場合は「-a」おオプションをつける。</p> <h3 id="コンテナの停止"><a href="#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E5%81%9C%E6%AD%A2">コンテナの停止</a></h3> <pre><code>docker stop <コンテナid> </code></pre> <p>停止したコンテナも含めてコンテナの一覧を表示したい場合は</p> <pre><code>[opc@publicpc1 ~]$ docker ps -all CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES af082867c083 nginx "/docker-entrypoint.…" 5 minutes ago Exited (0) 6 seconds ago nginx [opc@publicpc1 ~]$ </code></pre> <h3 id="コンテナの削除"><a href="#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E5%89%8A%E9%99%A4">コンテナの削除</a></h3> <pre><code>[opc@publicpc1 ~]$ docker rm <コンテナid> </code></pre> <h3 id="dockerのコンテナ内のシェルを操作"><a href="#docker%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E5%86%85%E3%81%AE%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%92%E6%93%8D%E4%BD%9C">dockerのコンテナ内のシェルを操作</a></h3> <pre><code>$ docker exec --interractive --tty <コンテナid> bash </code></pre> <p>でコンテナ内のシェルの中に入ることができる。<br /> <code>bash</code>じゃなくても<code>sh</code>でもよい。<br /> <code>--interractive</code>と<code>--tty</code>をまとめて<code>-it</code>と表記してもよい。</p> <pre><code>[opc@publicpc1 ~]$ docker exec -it c7822718378e bash root@c7822718378e:/# pwd / root@c7822718378e:/# whoami root root@c7822718378e:/# cd /home/ /home root@c7822718378e:~# exit exit </code></pre> <p>下記で、CentOS6のコンテナ内のシェルでコマンドを実行。</p> <pre><code># docker run -it --name centosA centos:6 /bin/bash </code></pre> <p>コンテナから一時的に抜けるには、[Ctrl+P]+[Ctrl+Q]を実行する。この状態ではバックグラウンドではコンテナが実行中なので<br /> 再接続するためには、 docker attach</p> <pre><code># docker attach centosA1 Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg. [root@b6067546d2da /]# </code></pre> <p>コンテナを抜けて終了するためにはexitする。</p> <pre><code>[root@b6067546d2da /]# exit exit [root@webpractice ~]# docker ps Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES </code></pre> <p>コンテナの再開には「docker start コンテナ名またはコンテナID」を実行する。</p> <h2 id="1-3.コンテナイメージの作成"><a href="#1-3.%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%AE%E4%BD%9C%E6%88%90">1-3.コンテナイメージの作成</a></h2> <p>まずは上書きしたいコンテナを調べる</p> <pre><code>[root@publicpc1 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c7822718378e nginx "/docker-entrypoint.…" 6 days ago Up 6 days 0.0.0.0:80->80/tcp, :::80->80/tcp modest_bassi </code></pre> <p>続いて、上書きしたいコンテナの中に入ってindex.htmlファイルを上書く。</p> <pre><code>[root@publicpc1 ~]# docker exec -it c7822718378e bash root@c7822718378e:/# echo "Hello Taro">/usr/share/nginx/html/index.html root@c7822718378e:/# exit exit </code></pre> <p>上書きしたコンテナを新規にイメージを作成</p> <pre><code>[root@publicpc1 ~]# docker commit c7822718378e hello_Taro sha256:ddb0b29808eb56539258060046bf06fdd12587a0057648f8d0714a4e40c11643 </code></pre> <p>上書きした元のコンテナを停止。</p> <pre><code>[root@publicpc1 ~]# docker stop c7822718378e c7822718378e </code></pre> <p>新規に作成したイメージからコンテナを起動。<br /> 注意点として、ローカル側のポートは使われていないポートにすること。<br /> 今回は8080番ポートを使用する。</p> <pre><code>[root@publicpc1 ~]# docker run -p 8080:80 -d --name hello_Taro hello_Taro 0931b542971f319c69eff05962efd69618a147064520b59396596f38df85b786 </code></pre> <p>ちゃんと接続できる確認。</p> <pre><code>[root@publicpc1 ~]# curl localhost:8080 Hello Taro </code></pre> <p>できました。</p> kawai_mizugorou tag:crieit.net,2005:PublicArticle/18221 2022-06-12T20:06:21+09:00 2022-06-12T20:06:50+09:00 https://crieit.net/posts/WSL2-clasp-WSL2-clasp-push-Error-Looks-like-you-are-offline 【WSL2/clasp】WSL2上からclasp pushするとError: Looks like you are offline.と怒られる問題を回避する <p>こんにちは、しきゆらです。<br /> 今回は、タイトルの通りWSL2からclaspを使おうとするとofflineと怒られる問題が起こったのでこれを回避する方法をメモしておきます。</p> <p>気が付くとWSL2からclasp pushをしようとすると、以下のようなエラーが出てしまってプッシュできない状態になっていました。<br /> よくわからないですが、たまにプッシュできたりするので何が悪いのかよくわかりません。<br /> WSLをインストールしなおしたりしても解決しませんでした。<br /> また、調べてもそれっぽい記事が出てこないので「おま環」ぽい気がしています。</p> <p>さて、これではWSL内で書いたGASをプッシュできません。<br /> これを回避する方法をメモしておきます。</p> <p>回避方法は単純で、Docker上からclasp pushをするだけ。<br /> 調べてみると、結構DockerでGASを管理したい人がいるようで、情報がそこそこありました。<br /> ということで、プロジェクト諸々をDocker上にマウントしてコマンド実行できるようにしていきます。<br /> なお、ここではGASをTypeScriptで書いたのちWebpackでビルドしたものをclaspコマンドでプッシュする流れです。<br /> 参考: <a target="_blank" rel="nofollow noopener" href="https://qiita.com/rei-ta/items/61b3fde6a069b77d335d">https://qiita.com/rei-ta/items/61b3fde6a069b77d335d</a></p> <h1 id="Dockerの準備"><a href="#Docker%E3%81%AE%E6%BA%96%E5%82%99">Dockerの準備</a></h1> <p>まずは、Dockerの準備をしましょう。<br /> Dockerのインストールは、WSLのホストであるWindows側に行えば良いようです。<br /> Dockerfileを以下のように作成します。</p> <pre><code>FROM node:slim RUN npm install @google/clasp -g </code></pre> <p>claspを実行する環境が必要なので、イメージとしてnodeを使います。<br /> サイズが小さいほうが何かと便利なのでnode:slimを使っていますが、nodeが動けばなんでもよいかと思います。<br /> また、claspを使えるようにインストールしておきます。</p> <p>続いて、docker-compose.ymlを作成します。</p> <pre><code>version: "3" services: clasp: build: . tty: true stdin_open: true volumes: - "/home/:/usr/src" working_dir: /usr/src/${user} </code></pre> <p>clasp loginしたのち、認証情報がhome直下にできるため/home/${user}をマウントしています。<br /> これで準備は完了。</p> <h1 id="offlineと怒られる問題を回避する"><a href="#offline%E3%81%A8%E6%80%92%E3%82%89%E3%82%8C%E3%82%8B%E5%95%8F%E9%A1%8C%E3%82%92%E5%9B%9E%E9%81%BF%E3%81%99%E3%82%8B">offlineと怒られる問題を回避する</a></h1> <p>Dockerを立ち上げていきます。<br /> <code>docker-compose run --rm -u ${id -u $usr} clasp /bin/bash</code><br /> シェルが立ち上がったら以下のコマンドでログインします。<br /> <code>clasp login --no-localhost</code><br /> これにて準備は完了です。<br /> あとは、コードを書いてWebapckでビルドしたものをclasp pushしましょう。</p> <pre><code>node@ded2ca180394:$ clasp push └─ /usr/src/path/to/project/appsscript.json └─ /usr/src/path/to/project/bundle.js Pushed 2 files. </code></pre> <p>問題なくプッシュできていますね。<br /> これにて回避完了です。</p> <h1 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h1> <p>手元の環境では、これにてofflineと怒られる問題を回避できました。<br /> ちょっと手間ですが、ひとまずは回避できました。<br /> 同じような問題が起こっている場合は試して見てください。</p> <p>今回は、ここまで。<br /> おしまい</p> しきゆら tag:crieit.net,2005:PublicArticle/18203 2022-05-31T00:00:59+09:00 2022-05-31T00:00:59+09:00 https://crieit.net/posts/docker-compose-conditional-branch-volume-mount-20220531 Docker Compose で条件に応じてマウントするボリュームを切り替える <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>Docker Compose を使って複数の似たようなユースケースで検証を繰り返している中で、</p> <ul> <li>この検証では Apache のドキュメントルートと MySQL のデータを永続化して試験したい</li> <li>その検証ではどちらも永続化しないで試験したい</li> <li>あの検証ではファイル数が膨大な上にオペレーションでその膨大なファイルに変更ををかけるので Apache のファイル永続化をしているとディスクIOがボトルネックになって検証に時間がかかり過ぎる</li> </ul> <p>という具合に、同じ Docker Compose のベースを使いつつもユースケースに応じてボリュームをマウントするかどうかを条件によって切り分けたくなりました。</p> <p>検証ごとに別リポジトリにフォークなりブランチなり切っていくと数が多くなってしまい管理しきれなくなる恐れがあるので、なるべくベースのコードは共通にしておきたいところです。</p> <p>そこで、「同じ Docker Compose のコードで、条件に応じて処理を変化させる(今回はマウントするボリュームを切り替える)」ということが必要になりました。</p> <h2 id="結果"><a href="#%E7%B5%90%E6%9E%9C">結果</a></h2> <p>最初に結果を記すと、今回は <code>docker-compose</code> を <code>up</code> する際に <code>-f</code>オプション を付ける、という方法を選択しました。</p> <h3 id="ボリュームをマウントしない場合"><a href="#%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%A0%E3%82%92%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88%E3%81%97%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88">ボリュームをマウントしない場合</a></h3> <pre><code class="bash">> docker-compose up -d </code></pre> <h3 id="ボリュームをマウントする場合"><a href="#%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%A0%E3%82%92%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88">ボリュームをマウントする場合</a></h3> <pre><code class="bash">> docker-compose -f docker-compose.yml -f docker-compose.volumes.yml up -d </code></pre> <p>このように使い分けるイメージです。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <p>上述で指定した各 <code>yml</code> ファイルは次のようになっています。</p> <h3 id="docker-compose.yml"><a href="#docker-compose.yml">docker-compose.yml</a></h3> <pre><code class="yml">version: '3.8' services: web: build: context: ./apache/docker dockerfile: Dockerfile args: WEB_ROOT_DIRECTORY: $WEB_ROOT_DIRECTORY ## 略 volumes: # workspace - ./workspace:/workspace # docker settings template - ./template:/template ## 略 db: build: context: ./mysql/docker dockerfile: Dockerfile ## 略 volumes: # workspace - ./workspace:/workspace # docker settings template - ./template:/template ## 略 </code></pre> <p>オプションなしで使用するデフォルトの <code>docker-compose.yml</code> はエントリポイントのシェルスクリプトや設定、ログの置き場所など最低限のディレクトリをマウントするに留めています。</p> <h3 id="docker-compose.volumes.yml"><a href="#docker-compose.volumes.yml">docker-compose.volumes.yml</a></h3> <pre><code class="yml">version: '3.8' services: web: volumes: # apache virtual host - ./apache/www:/var/www/$WEB_ROOT_DIRECTORY/web db: volumes: # mysql data - ./mysql/data:/var/lib/mysql/data </code></pre> <p>一方、ボリュームマウント用の <code>yml</code> ファイルでは冒頭の通り Apache のドキュメントルート想定のディレクトリや MySQL のデータファイルのディレクトリをマウントするようにしています。</p> <p>これにより、オプション指定のない場合は後者のファイルが読み込まれないことによりドキュメントルートやデータファイルをマウントせず、オプションを付けるとマウントする、というように挙動を切り替えられる、という寸法です。</p> <p>ただし、このくらいで済むのでまだ良いですがこれが複雑化すると大量の <code>-f</code>オプション と Composeファイル による長大なコマンドになってしまう恐れがあるのでその点は要改善ですかね。現時点でも <code>readme.md</code> とかにコマンドを書いておかないと一々打ち込んでいられないレベルですし。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="-f オプション"><a href="#-f+%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3">-f オプション</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/reireias/items/ecb81e248314253eb156">docker-compose.ymlをDRYに書くテクニック2選 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.ykicchan.dev/posts/2020-07-13">docker-compose.yml を環境ごとに分割する - yKicchan's blog</a></li> </ul> <h3 id="-f オプションの先"><a href="#-f+%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E5%85%88">-f オプションの先</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://suin.io/535">docker-compose.ymlが環境別に複数ある場合はCOMPOSE_FILEを定義しておくと幸せになれる</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://ikasamak503.hatenablog.com/entry/dry-docker-compose-yaml">docker-compose で複数環境を構築するときの設定をなるべく DRY に書く - ikasama over technology</a></li> </ul> <h3 id="Compose ファイルの指定"><a href="#Compose+%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E6%8C%87%E5%AE%9A">Compose ファイルの指定</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://docs.docker.jp/compose/reference/envvars.html#compose-file">Compose CLI 環境変数 — Docker-docs-ja 20.10 ドキュメント</a></li> </ul> <h3 id="(未使用) 環境変数"><a href="#%28%E6%9C%AA%E4%BD%BF%E7%94%A8%29+%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0">(未使用) 環境変数</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://matsuand.github.io/docs.docker.jp.onthefly/compose/environment-variables/#the-env-file">Compose における環境変数 | Docker ドキュメント</a></li> </ul> <h3 id="ボリュームのマウント"><a href="#%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%A0%E3%81%AE%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88">ボリュームのマウント</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://zenn.dev/randd/articles/84ac7de7f22800">Dockerのマウントについて</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/18202 2022-05-30T23:58:04+09:00 2022-05-30T23:58:04+09:00 https://crieit.net/posts/docker-container-refer-hostmachine-hosts-20220530 Dockerコンテナ 上の名前解決とホストマシンの Windows の hosts <p>とある試験で Dockerコンテナ からのみ特別に名前解決したい、というケースが生じました。</p> <p>そこでホストマシンの Windows の hosts が使えないか検証したのでメモ。</p> <h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2> <pre><code class="bash"># yum install -y bind-utils </code></pre> <p>まず今回検証したい Dockerコンテナ はデフォルトだと <code>nslookup</code> コマンドが入っていないのでインストール (<code>bind-utils</code> の中に含まれている)。</p> <pre><code>#192.0.2.1 hoge.example1.jp </code></pre> <p>続いてホストマシンの Windows の <code>hosts</code> を上述のように記述。あえてコメントアウトしてあります。</p> <p>なお、 <code>hoge.example1.jp</code> は公開 DNSサーバ にはレコードが存在しないドメインだとします。</p> <pre><code class="bash"># nslookup > hoge.example1.jp Server: 127.0.0.11 Address: 127.0.0.11#53 ** server can't find hoge.example1.jp: NXDOMAIN </code></pre> <p>この状態で Dockerコンテナ 上から <code>nslookup</code> 。上述の通り DNSサーバ にレコードが存在しない前提なので、名前解決できません。</p> <pre><code># nslookup > example1.jp Server: 127.0.0.11 Address: 127.0.0.11#53 Non-authoritative answer: Name: example1.jp Address: 192.0.2.11 </code></pre> <p>逆に、 DNSサーバ にレコードが存在する <code>example1.jp</code> は名前解決できます。想定通りですね。</p> <pre><code>192.0.2.1 hoge.example1.jp </code></pre> <p>続いてホストマシンの Windows の <code>hosts</code> に記述をした場合です。</p> <pre><code class="bash"># nslookup > hoge.example1.jp Server: 127.0.0.11 Address: 127.0.0.11#53 Non-authoritative answer: Name: hoge.example1.jp Address: 192.0.2.1 </code></pre> <p>名前解決できました。このことから、 Dockerコンテナ はホストマシンの <code>hosts</code> を参照することが分かりました。</p> <p>これで検証が進められます。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/nkojima/items/083eed7f835547b0b0f7">使えないコマンドがある時の対応方法 - Qiita</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/18196 2022-05-23T23:59:20+09:00 2022-05-23T23:59:20+09:00 https://crieit.net/posts/docker-compose-set-default-enviroment-variables-20220522 Docker Compose で使用する環境変数にデフォルト値を設定する <p>Docker Compose で使用する <code>.env</code> の環境変数にデフォルト値を設定する方法についてメモ。</p> <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>PHP Webアプリケーション用のコンテナからDB用のコンテナに接続する際、DB名やユーザ名・パスワードを任意の値に設定したい。</p> <p>ただし <code>.env</code> は Git 管理にはしたくないので標準では <code>sample.env</code> 等に逃がしており、うっかりファイルをコピー・リネームし忘れていたり、あるいはキー名をタイポして値が消えてしまったりすると困る……ということでデフォルト値を設定できないか、と考えました。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <h3 id="docker-compose.yml"><a href="#docker-compose.yml">docker-compose.yml</a></h3> <pre><code class="yml">version: '3.7' volumes: logs: driver: local services: php: build: context: ./_docker/dockerfiles/ dockerfile: Dockerfile working_dir: /var/www command: php -S 0.0.0.0:8080 -t public ports: - 8080:8080 db: image: mariadb restart: always ports: - ${MYSQL_PORT:-3306}:${MYSQL_PORT:-3306} environment: - MYSQL_ROOT_PASSWORD=pwd - MYSQL_DATABASE=${MYSQL_DBNAME:-test} - MYSQL_USER=${MYSQL_USER:-user} - MYSQL_PASSWORD=${MYSQL_PASSWORD:-pwd} </code></pre> <h3 id=".env (サンプル)"><a href="#.env+%28%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%29">.env (サンプル)</a></h3> <pre><code class="env">MYSQL_DBNAME=foo_db MYSQL_USER=foo_user MYSQL_PASSWORD="Password-1234" MYSQL_HOST=192.0.2.1 MYSQL_PORT=3306 </code></pre> <p>早速ですが用意したコード。</p> <p>まず基本的に <code>.env</code> を用意すれば、 <code>${HOGE}</code> の形式で環境変数をセットできます。</p> <p>今回はそこに <code>${HOGE:-FUGA}</code> と、コロン(<code>:</code>)とハイフン(<code>-</code>)を付けた値を追加しました。これにより、「<code>.env</code> に <code>HOGE=PIYO</code> のように <code>HOGE</code> に値がセットされていれば <code>PIYO</code> を、そうでなければデフォルト値として <code>:-</code> の後の文字列 (この場合は <code>FUGA</code>) をセット」となります。</p> <p>例えば上述の <code>- MYSQL_DATABASE=${MYSQL_DBNAME:-test}</code> の部分では、 MariaDB のコンテナイメージに対して <code>MYSQL_DATABASE</code> キーへ <code>.env</code> の <code>MYSQL_DBNAME</code> に値がセットされていればその値を、そうでなければ <code>test</code> をセット、となります。</p> <p>なお <code>-</code> がない場合は empty も許容されるので、空文字列が環境変数にセットされるようです。今回はどれも空文字列では都合が宜しくないので全てハイフンありで統一。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="デフォルト値"><a href="#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E5%80%A4">デフォルト値</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/fagai/items/b944950b26af19453c02">案外知られてないdocker-composeの環境変数定義の記法 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.docker.com/compose/compose-file/#interpolation">Compose specification | Docker Documentation</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://matsuand.github.io/docs.docker.jp.onthefly/compose/environment-variables/">Compose における環境変数 | Docker ドキュメント</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/18195 2022-05-23T23:58:56+09:00 2022-05-23T23:58:56+09:00 https://crieit.net/posts/docker-compose-change-enviroment-variables-file-20220523 Docker Compose に渡す環境変数ファイルを変更する <p>Docker Compose に渡す環境変数に .env 以外のファイルから渡したいと考えたのでメモしておきます。</p> <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>アプリケーション開発環境等で開発環境用の <code>.development.env</code> と本番環境用の <code>.production.env</code> を用意したとして、この2つのどちらかから Docker Compose に環境変数を渡したい。</p> <p>開発環境なのでアプリ側で使用する環境変数と Dockerコンテナ 内で使用する環境変数を統一したい、と。</p> <p>ただし、デフォルトでは Docker Compose は <code>.env</code> からしか環境変数を読み取ってくれません。これをどうにかしたい。</p> <h2 id="コマンド"><a href="#%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89">コマンド</a></h2> <pre><code class="bash">> docker-compose --env-file .development.env up -d </code></pre> <p>ということでコマンドですが、 <code>docker-compose</code> コマンドに <code>--env-file</code> でパラメータを渡してあげると <code>.env</code> 以外のファイルも環境変数のソースとして渡すことができます。</p> <h2 id="(余談) コマンド実行時の --env-file パラメータと .envファイル と docker-compose.yml の env_file キー"><a href="#%28%E4%BD%99%E8%AB%87%29+%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E5%AE%9F%E8%A1%8C%E6%99%82%E3%81%AE+--env-file+%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%81%A8+.env%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB+%E3%81%A8+docker-compose.yml+%E3%81%AE+env_file+%E3%82%AD%E3%83%BC">(余談) コマンド実行時の --env-file パラメータと .envファイル と docker-compose.yml の env_file キー</a></h2> <p>さて、ここから少しややこしい話を。</p> <p>Docker Compose 周りでは環境変数関連で見出しに挙げた3つの方法があるようです。</p> <p><code>.env</code> については Docker Compose で使用できる環境変数ファイル。これは良いですね。</p> <p>この <code>.env</code> をそれ以外のファイル名・ディレクトリのファイルから読み取るように変更できるのが <code>docker-compose</code>コマンド 実行時の <code>--env-file</code> パラメータ。</p> <p>ここまでは <strong><code>docker-compose.yml</code> 内で使用できる</strong> 環境変数です。</p> <p>それでは最後、 <code>docker-compose.yml</code> の <code>env_file</code>キー は何か。</p> <pre><code>version: '3.7' services: db: env_file: - .dvelopment.env </code></pre> <p>最後の <code>env_file</code> は <code>docker-compose.yml</code> 内に記述できるパラメータで、これを使って環境変数のファイルを指定することができます。</p> <p>ただし、このパラメータで指定した環境変数は、 <strong>起動したコンテナ内からは参照できますが、 <code>docker-compose.yml</code> 内からは参照できません</strong>。</p> <p>ということで、今回やりたいこととはマッチしません。そもそもの目的が異なる、ということですね。</p> <p>過去の先人達のように自分も嵌まったのでこのことも併せてメモしておきます。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://zenn.dev/rhene/scraps/781fdbecd340d3">docker-composeで環境変数が読み込まれない?</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/SolKul/items/989727aeeafcae28ecf7">docker-composeのenv_fileと.envファイルの違い - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.docker.jp/compose/environment-variables.html">Compose における環境変数 — Docker-docs-ja 19.03 ドキュメント</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.docker.com/compose/environment-variables/">Environment variables in Compose | Docker Documentation</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/18186 2022-05-10T22:39:48+09:00 2022-05-10T22:39:48+09:00 https://crieit.net/posts/docker-php-7-alpine-use-composer-and-xdebug-20220510 Docker の php:7-alpine イメージで Composer と Xdebug を使えるようにする <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://github.com/slimphp/Slim-Skeleton">slimphp/Slim-Skeleton</a> を利用したいと考えました。</p> <p>手元の端末で開発しようとしたところ、 XAMPP に Xdebug を入れ忘れていたことに気付きました。しかも、 XAMPP の PHP のバージョンで Xdebug のインストールが止まってしまいました。</p> <p>そこで、スケルトンプロジェクトに付随している Docker Compose での開発を試みましたが、この Docker Compose 内で pull してくるイメージは Composer も Xdebug もないので入れることにしました。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <h3 id="ディレクトリ構造"><a href="#%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A7%8B%E9%80%A0">ディレクトリ構造</a></h3> <pre><code>root/ ├ _docker/ // Dockerに関する設定置き場 │ ├ dockerfiles/ │ │ ├ settings/ │ │ │ └ php.ini // PHPの設定 (Xdebug 有効化) │ │ │ │ │ └ Dockerfile │ │ │ ├ mysql/ // MariaDB 用ディレクトリ │ │ └ .gitkeep │ │ │ └ phpmyadmin/ │ ├ conf/ │ │ └ phpmyadmin-misc.ini // phpMyAdmin の設定 (メモリ上限など) │ │ │ └ sessions/ │ └ .gitkeep │ └ docker-compose.yml </code></pre> <p>Docker に関する部分のみ列挙。</p> <h3 id="docker-compose.yml"><a href="#docker-compose.yml">docker-compose.yml</a></h3> <pre><code class="yml">version: '3.7' volumes: logs: driver: local services: slim: build: context: ./_docker/dockerfiles/ dockerfile: Dockerfile working_dir: /var/www command: php -S 0.0.0.0:8080 -t public environment: docker: "true" ports: - 8080:8080 volumes: - .:/var/www - ./logs:/var/www/logs db: image: mariadb restart: always ports: - 3306:3306 volumes: - ./_docker/mysql/mysql:/var/lib/mysql - ./_docker/mysql/initdb.d:/docker-entrypoint-initdb.d environment: - MYSQL_ROOT_PASSWORD=pwd - MYSQL_DATABASE=test - MYSQL_USER=user - MYSQL_PASSWORD=pwd phpmyadmin: image: phpmyadmin/phpmyadmin volumes: - ./_docker/phpmyadmin/sessions:/sessions - ./_docker/phpmyadmin/conf/phpmyadmin-misc.ini:/usr/local/etc/php/conf.d/phpmyadmin-misc.ini environment: - PMA_ARBITRARY=1 - PMA_HOST=db - PMA_USER=user - PMA_PASSWORD=pwd ports: - 8081:80 </code></pre> <p>変更点は以下。</p> <ul> <li>PHP 用環境: <code>Dockerfile</code> を使ったイメージにカスタマイズ</li> <li>DB: MariaDB のイメージをそのまま利用 <ul> <li><code>environment</code> のパラメータはそのまま使用。アプリケーションや phpMyAdmin 側と動機は取れていないですがひとまずはこれで……</li> </ul></li> <li>phpMyAdmin: これも phpMyAdmin 公式イメージを流用</li> </ul> <h3 id="_docker/dockerfiles/Dockerfile"><a href="#_docker%2Fdockerfiles%2FDockerfile">_docker/dockerfiles/Dockerfile</a></h3> <pre><code class="Dockerfile">FROM php:7-alpine RUN apk --update add curl RUN set -ex \ && apk --no-cache add \ autoconf build-base RUN pecl install xdebug RUN docker-php-ext-enable xdebug RUN docker-php-ext-install pdo_mysql COPY settings/php.ini /usr/local/etc/php/conf.d RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer </code></pre> <p><code>php:7-alpine</code> をベースに Xdebug と Composer を追加。</p> <h3 id="_docker/dockerfiles/settings/php.ini"><a href="#_docker%2Fdockerfiles%2Fsettings%2Fphp.ini">_docker/dockerfiles/settings/php.ini</a></h3> <pre><code class="ini">xdebug.mode=coverage </code></pre> <p>Xdebug でカバレッジを有効化するための設定を追加するため。なお、 <code>Dockerfile</code> で <code>COPY</code> する際のホストマシンでのパスは <strong><code>Dockerfile</code> の存在するディレクトリから下でないと参照できない</strong> という地味な制約があるので <code>dockerfiles</code> ディレクトリをわざわざ掘りました。</p> <h3 id="_docker/phpmyadmin/conf/phpmyadmin-misc.ini"><a href="#_docker%2Fphpmyadmin%2Fconf%2Fphpmyadmin-misc.ini">_docker/phpmyadmin/conf/phpmyadmin-misc.ini</a></h3> <pre><code class="ini">allow_url_fopen = Off max_execution_time = 600 memory_limit = 64M post_max_size = 64M upload_max_filesize = 64M </code></pre> <p>メモリ上限等のカスタマイズ。</p> <hr /> <p>これで今回はカバレッジ出力まで動作することを確認しました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="Xdebug"><a href="#Xdebug">Xdebug</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/sachiko-kame/items/bf5480f4d7c751ab28aa">PHPUnitでHTMLコードカバレッジを出すまで(Docker使用) - Qiita</a></li> </ul> <blockquote> <p>Warning: XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set</p> </blockquote> <p>が出たので step3 について実施。</p> <p>なお、今回のケースでは</p> <pre><code>extension=xdebug.so </code></pre> <p>は不要だった。</p> <h2 id="Dockerfile"><a href="#Dockerfile">Dockerfile</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://crudzoo.com/blog/php-docker">Dockerで作るNginx + PHP7 + Xdebug環境 | Crudzoo</a></li> </ul> <p>ほぼこれでOK.</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/ucan-lab/items/fbf021bf69896538e515">php-alpineコンテナにxdebugをインストールする時にハマったメモ - Qiita</a></li> </ul> <p>こちらも参照。 <code>php -v</code> で <code>with Xdebug</code> と付いていればOK。</p> <h4 id="Dockerfile の COPY"><a href="#Dockerfile+%E3%81%AE+COPY">Dockerfile の COPY</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://scrapbox.io/taka521-tech-notes/%E3%80%90Docker%E3%80%91COPY%E3%81%A7%E6%8C%87%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%9F%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AF%E3%80%81Dockerfile%E3%81%8C%E5%AD%98%E5%9C%A8%E3%81%99%E3%82%8B%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%8B%E3%82%89%E3%81%AE%E7%9B%B8%E5%AF%BE%E3%83%91%E3%82%B9%E3%81%A7%E3%80%81%E8%A6%AA%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%82%92%E8%A6%8B%E3%82%8C%E3%81%AA%E3%81%84">【Docker】COPYで指定されたファイルは、Dockerfileが存在するディレクトリからの相対パスで、親ディレクトリを見れない - タカの技術ノート</a></li> </ul> <h3 id="Mariadb"><a href="#Mariadb">Mariadb</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://mebee.info/2020/04/07/post-8227/">dockerを使用してmariadbを構築する | mebee</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/tarch710/items/1236a23f7ffde4c512f2">開発環境をDockerにしたら、PDOでcould not find driverが出た - Qiita</a></li> </ul> <blockquote> <p>could not find driver</p> </blockquote> <p>普通に考えたら確かにドライバがないので追加して解決。</p> <h3 id="シェル"><a href="#%E3%82%B7%E3%82%A7%E3%83%AB">シェル</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yutachaos/items/56dd7ea09d7e2b0d9173">dockerでalpine linux ベースのcontainerに入って、shellを使いたいとき。 - Qiita</a></li> </ul> <p>bash ではなく ash 。 <code>bin/ash</code> 指定。</p> <h3 id="sr -c"><a href="#sr+-c">sr -c</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://genzouw.com/entry/2020/01/28/120014/1910/">docker-compose.ymlのcommandプロパティに複数コマンドを設定する方法 | ゲンゾウ用ポストイット</a></li> </ul> <p>最終的には使わずに済みましたが念のためメモ。</p> arm-band tag:crieit.net,2005:PublicArticle/18184 2022-05-04T05:16:16+09:00 2022-05-15T23:54:05+09:00 https://crieit.net/posts/Docker-Kubernetes-gitLab DockerとKubernetes <h1 id="0 前提"><a href="#0+%E5%89%8D%E6%8F%90">0 前提</a></h1> <p>Oracle LinuxとWindows</p> <h1 id="1 環境構築"><a href="#1+%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89">1 環境構築</a></h1> <p>準備</p> <h2 id="1-1 Dockerオフラインインストール"><a href="#1-1+Docker%E3%82%AA%E3%83%95%E3%83%A9%E3%82%A4%E3%83%B3%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">1-1 Dockerオフラインインストール</a></h2> <p>参考にしたURLは<code>https://qiita.com/kod314/items/e574ac12c23598e0d903</code>。<br /> オンラインインストールの場合は、<br /> <a target="_blank" rel="nofollow noopener" href="https://qiita.com/kichise/items/f8e56c6d2d08eaf4a6a0">https://qiita.com/kichise/items/f8e56c6d2d08eaf4a6a0</a><br /> の手順に従えば可能。</p> <p>今回はオフラインインストールを実行しようと思う。社内規則によりDockerをインストールするサーバがインターネット接続できない場合がある。その場合、インターネット接続できる自席端末からネットに接続してDockerのインストーラーをダウンロード。それをDockerをインストールしたいサーバに転送して実行させる。</p> <h3 id="1-1-1 OS確認"><a href="#1-1-1+OS%E7%A2%BA%E8%AA%8D">1-1-1 OS確認</a></h3> <p>まずはOSのversionを確認。</p> <pre><code>$ uname -a Linux publicpc1 5.4.17-2136.305.5.3.el8uek.x86_64 #2 SMP Thu Mar 17 10:45:33 PDT 2022 x86_64 x86_64 x86_64 GNU/Linux </code></pre> <p>より詳細</p> <pre><code>#cat /etc/os-release NAME="Oracle Linux Server" VERSION="8.5" ID="ol" ID_LIKE="fedora" VARIANT="Server" VARIANT_ID="server" VERSION_ID="8.5" PLATFORM_ID="platform:el8" PRETTY_NAME="Oracle Linux Server 8.5" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:oracle:linux:8:5:server" HOME_URL="https://linux.oracle.com/" BUG_REPORT_URL="https://bugzilla.oracle.com/" ORACLE_BUGZILLA_PRODUCT="Oracle Linux 8" ORACLE_BUGZILLA_PRODUCT_VERSION=8.5 ORACLE_SUPPORT_PRODUCT="Oracle Linux" ORACLE_SUPPORT_PRODUCT_VERSION=8.5 </code></pre> <p>Linuxカーネルの確認</p> <pre><code>$ hostnamectl Static hostname: publicpc1 Icon name: computer-vm Chassis: vm Machine ID: 4c3dc5bfa43b47b8b66789ce778a0711 Boot ID: 226a196eedc746e2848a6f15e9afeb0b Virtualization: kvm Operating System: Oracle Linux Server 8.5 CPE OS Name: cpe:/o:oracle:linux:8:5:server Kernel: Linux 5.4.17-2136.305.5.3.el8uek.x86_64 Architecture: x86-64 </code></pre> <p>x86_64と記載されているので、Intel(AMD)の64bitオペレーティングシステムであることがわかる。</p> <h3 id="1-1-2 Docker engineをインストール"><a href="#1-1-2+Docker+engine%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">1-1-2 Docker engineをインストール</a></h3> <p>Docker本体であるDocker Engineと、同時に複数のコンテナを操作するツールであるDocker Composeをダウンロードする。<br /> 参考にした公式:https://docs.docker.com/engine/install/binaries/</p> <p>まずはdocker本体<br /> <a target="_blank" rel="nofollow noopener" href="https://download.docker.com/linux/static/stable/x86_64/">https://download.docker.com/linux/static/stable/x86_64/</a><br /> →バージョンがいろいろあるので、最新のdocker-20.10.9.tgz をダウンロードしてみた。<br /> 自分の端末(クライアント側にダウンロードしたファイルをLinuxサーバに転送してから解凍する。</p> <pre><code>$ ls -al /home/opc/docker-20.10.9.tgz -rw-r--r--. 1 opc opc 63350495 May 4 04:23 /home/opc/docker-20.10.9.tgz </code></pre> <p>展開</p> <pre><code>$ tar zxvf docker-20.10.9.tgz </code></pre> <p>すると、カレントディレクトリにdockerディレクトリが作成される。<br /> dockerディレクトリの中身を<code>/usr/bin/</code>配下にコピーする。</p> <pre><code>$ sudo cp docker/* /usr/bin/ </code></pre> <p>試しに起動するには</p> <pre><code>$ sudo dockerd & </code></pre> <h3 id="1-1-3 Docker Composeをインストール"><a href="#1-1-3+Docker+Compose%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">1-1-3 Docker Composeをインストール</a></h3> <p>続いてはdocker-compose<br /> インストール手順は以下に記載されているので以降この指示に従う。<br /> <a target="_blank" rel="nofollow noopener" href="https://github.com/docker/compose/blob/v2/README.md">https://github.com/docker/compose/blob/v2/README.md</a></p> <p>さきほど(1-1-1節)でOSとCPUを確認したので、<br /> それに従って<code>docker-compose-linux-x86_64</code>をダウンロードする。<br /> <a target="_blank" rel="nofollow noopener" href="https://github.com/docker/compose/releases">https://github.com/docker/compose/releases</a></p> <p>自分のwindows端末(クライアント側)にダウンロードした<code>docker-compose-linux-x86_64</code>をdockerをインストールしたLinuxサーバに転送。<br /> 転送したら、バイナリファイルの名前を<code>docker-compose</code>にリネーム。</p> <pre><code>$ mv docker-compose-linux-x86_64 docker-compose </code></pre> <p>docker-composeをいどうする。移動する先は目的に応じて移動先が異なる。<br /> 今回は</p> <pre><code>$ sudo mv docker-compose /usr/local/bin/ $ sudo chmod +x /usr/local/bin/docker-compose $ docker-compose -v Docker Compose version v2.5.0 </code></pre> <h3 id="1-1-4 Docker イメージのオフラインで利用する"><a href="#1-1-4+Docker+%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%AA%E3%83%95%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%A7%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B">1-1-4 Docker イメージのオフラインで利用する</a></h3> <pre><code>$ tar zxvf helloworld_img.tar.gz $ docker load < helloworld_img # dockerイメージをload $ docker images # hello-worldイメージが存在することを確認 </code></pre> <h3 id="1-1-5 Dockerグループ作成"><a href="#1-1-5+Docker%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E4%BD%9C%E6%88%90">1-1-5 Dockerグループ作成</a></h3> <p>Docker daemonはrootユーザで実行しなければならず、毎回sudoを使うのは面倒である。<br /> その場合、dockerグループを作成してそこに任意のユーザを所属させてあげる。</p> <pre><code>groupadd docker usermod -aG docker opc </code></pre> <h3 id="1-1-6 トラブルシュート"><a href="#1-1-6+%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%88">1-1-6 トラブルシュート</a></h3> <p>docklerをサービスでenebleにしようと思ったができなかった。</p> <pre><code>[root@publicpc1 system]# systemctl enable docker Failed to enable unit: Unit file docker.service does not exist. </code></pre> <p>以下のサイトを参考に対応してみた。<br /> <a target="_blank" rel="nofollow noopener" href="https://jhooq.com/docker-daemon-centos/">https://jhooq.com/docker-daemon-centos/</a></p> <p>/usr/lib/systemd/system配下にdocker.socketファイルを作成し以下の内容を記載した。</p> <pre><code>[Unit] Description=Docker Socket for the API [Socket] ListenStream=/var/run/docker.sock SocketMode=0660 SocketUser=root SocketGroup=docker [Install] WantedBy=sockets.target </code></pre> <p>続いて、/usr/lib/systemd/system/配下に<code>docker.service</code>を作成する。</p> <pre><code>[Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target docker.socket firewalld.service containerd.service Wants=network-online.target Requires=docker.socket containerd.service [Service] Type=notify #the default is not to use systemd for cgroups because the delegate issues still #exists and systemd currently does not support the cgroup feature set required #for containers run by docker ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always #Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229. #Both the old, and new location are accepted by systemd 229 and up, so using the old location #to make them work for either version of systemd. StartLimitBurst=3 #Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230. #Both the old, and new name are accepted by systemd 230 and up, so using the old name to make #this option work for either version of systemd. StartLimitInterval=60s #Having non-zero Limit*s causes performance problems due to accounting overhead #in the kernel. We recommend using cgroups to do container-local accounting. LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity #Comment TasksMax if your systemd version does not support it. #Only systemd 226 and above support this option. TasksMax=infinity #set delegate yes so that systemd does not reset the cgroups of docker containers Delegate=yes #kill only the docker process, not all processes in the cgroup KillMode=process OOMScoreAdjust=-500 [Install] WantedBy=multi-user.target </code></pre> <p>この中身をみると<code>Requires=docker.socket containerd.service</code>と記載されている通り、containerd.serviceが必要。なので/usr/lib/systemd/system配下にcontainerd.serviceサービスを作成する必要がある。</p> <pre><code>#Copyright The containerd Authors. #Licensed under the Apache License, Version 2.0 (the "License"); #you may not use this file except in compliance with the License. #You may obtain a copy of the License at #http://www.apache.org/licenses/LICENSE-2.0 #Unless required by applicable law or agreed to in writing, software #distributed under the License is distributed on an "AS IS" BASIS, #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #See the License for the specific language governing permissions and #limitations under the License. [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target local-fs.target [Service] ExecStartPre=-/sbin/modprobe overlay ExecStart=/usr/bin/containerd Type=notify Delegate=yes KillMode=process Restart=always RestartSec=5 #Having non-zero Limit*s causes performance problems due to accounting overhead #in the kernel. We recommend using cgroups to do container-local accounting. LimitNPROC=infinity LimitCORE=infinity LimitNOFILE=infinity #Comment TasksMax if your systemd version does not supports it. #Only systemd 226 and above support this version. TasksMax=infinity OOMScoreAdjust=-999 [Install] WantedBy=multi-user.target </code></pre> <p>上記を作成する。</p> <p>ちゃんとリロードしとく。</p> <pre><code>systemctl daemon-reload </code></pre> <h2 id="1-2.Kubernetesの準備"><a href="#1-2.Kubernetes%E3%81%AE%E6%BA%96%E5%82%99">1-2.Kubernetesの準備</a></h2> <h3 id="1-2-1. インストール"><a href="#1-2-1.+%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">1-2-1. インストール</a></h3> <p>オフライン環境でKubernetesを構築する手順。<br /> 手順の参考にしたのは以下<br /> <a target="_blank" rel="nofollow noopener" href="https://docs.genesys.com/Documentation/GCXI/latest/Dep/DockerOffline">https://docs.genesys.com/Documentation/GCXI/latest/Dep/DockerOffline</a></p> <p>まずはネットにつながる端末から</p> <pre><code>$ pwd /etc/yum.repos.d $ cat kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg </code></pre> <p>以下のコマンドを実行してファイルをダウンロード。<br /> <code><your_rpm_dir></code>の部分は自分で適当なディレクトリを作成して<br /> そこのパスを指定。</p> <pre><code>yumdownloader --assumeyes --destdir= --resolve yum-utils kubeadm-1.21.* kubelet-1.21.* kubectl-1.21.* ebtables </code></pre> <p>続いて、ダウンロードしたファイルをインストールしていく。</p> <pre><code>yum install -y --cacheonly --disablerepo=* /*.rpm </code></pre> <p>インストールする際、バージョンが異なるファイルが存在してインストールエラーになるかもしれない。<br /> その場合は、必要のないバージョンのファイルは削除してから<br /> 再度インストールするとうまくいく。<br /> うまくいくと以下のようになる。</p> <pre><code>Complete! </code></pre> <p>必要なイメージが揃っているか確認してみよう。</p> <pre><code>$ kubeadm config images list I0504 23:15:36.977910 309762 version.go:254] remote version is much newer: v1.24.0; falling back to: stable-1.21 k8s.gcr.io/kube-apiserver:v1.21.12 k8s.gcr.io/kube-controller-manager:v1.21.12 k8s.gcr.io/kube-scheduler:v1.21.12 k8s.gcr.io/kube-proxy:v1.21.12 k8s.gcr.io/pause:3.4.1 k8s.gcr.io/etcd:3.4.13-0 k8s.gcr.io/coredns/coredns:v1.8.0 </code></pre> <h3 id="1-2-2. kubectlの概要"><a href="#1-2-2.+kubectl%E3%81%AE%E6%A6%82%E8%A6%81">1-2-2. kubectlの概要</a></h3> <p>参考URL:https://kubernetes.io/ja/docs/reference/kubectl/_print/<br /> Kubernetesクラスタを操作するコマンド</p> <h1 id="2.Docker入門"><a href="#2.Docker%E5%85%A5%E9%96%80">2.Docker入門</a></h1> kawai_mizugorou tag:crieit.net,2005:PublicArticle/18125 2022-02-25T22:46:15+09:00 2022-02-25T22:46:15+09:00 https://crieit.net/posts/change-timzezone-in-docker-for-wordpress-post-failed-20220224 Docker 上の Almalinux のタイムゾーン設定について <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>AlmaLinux ベースの自作LAMP環境構築用 Docker で WordPress を動かしたところ、投稿が「予約投稿の失敗」となってしまい正常に投稿できない現象に遭遇したため対処。</p> <h2 id="現象"><a href="#%E7%8F%BE%E8%B1%A1">現象</a></h2> <p><a href="https://crieit.now.sh/upload_images/49f0d2b150a7b5d422313af680baf9ae62124ffe1e1d2.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/49f0d2b150a7b5d422313af680baf9ae62124ffe1e1d2.jpg?mw=700" alt="今までの設定で発生していた現象" /></a></p> <p>今までの Docker Compose 環境で発生していた現象が上述の画像。普通に投稿したにも関わらず、「予約投稿の失敗」となってしまいます。</p> <p>困ったことに WordPress の管理画面で見ると日時はずれていない (WordPress インストール時のサンプル投稿「Hello World!」の投稿日時とほぼ同じ) ので、ぱっと見原因が掴みづらいところ。</p> <p>ちなみに、 <code>wp_posts</code> のテーブルを直接見たところ、 <code>post_date</code>, <code>post_date_gmt</code>, <code>post_modified</code>, <code>post_modified_gmt</code> が全て同じ日時になっていました。</p> <p>……あれ、 <code>_gmt</code> 系はグリニッジ標準時刻なので日本の時刻とは9時間ずれるはずでは……。ということで、どうもこの辺りが宜しくなさそうです。</p> <p>なお、この時の Dockerfile 等の各種設定は次のようになっていました。</p> <h3 id="Dockerfile (共通)"><a href="#Dockerfile+%28%E5%85%B1%E9%80%9A%29">Dockerfile (共通)</a></h3> <pre><code class="dockerfile">RUN \cp -pf /usr/share/zoneinfo/Japan /etc/localtime </code></pre> <h3 id="php.ini"><a href="#php.ini">php.ini</a></h3> <pre><code class="ini">[Date] ; Defines the default timezone used by the date functions ; http://php.net/date.timezone ;date.timezone = date.timezone = 'Asia/Tokyo' </code></pre> <h3 id="my.cnf 等"><a href="#my.cnf+%E7%AD%89">my.cnf 等</a></h3> <p>MySQL 側では特に指定なし。</p> <h2 id="変更"><a href="#%E5%A4%89%E6%9B%B4">変更</a></h2> <p>これらの設定を次のようにしました。</p> <h3 id="Dockerfile (共通)"><a href="#Dockerfile+%28%E5%85%B1%E9%80%9A%29">Dockerfile (共通)</a></h3> <pre><code class="dockerfile">RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux \ && dnf -y update && dnf -y install \ # 略 # timezone glibc-locale-source \ # locale, timezone && localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 \ && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime # local & timezone ENV LANG="ja_JP UTF-8" \ LANGUAGE="ja_JP:ja" \ LC_ALL="ja_JP.UTF-8" \ TZ="Asia/Tokyo" </code></pre> <p>やり方を大幅に変更。強制コピーで localtime ファイルを上書きするのではなく、段取りを踏んで設定するようにしました。</p> <h3 id="php.ini"><a href="#php.ini">php.ini</a></h3> <pre><code class="ini">[Date] ; Defines the default timezone used by the date functions ; http://php.net/date.timezone ;date.timezone = date.timezone = 'Asia/Tokyo' </code></pre> <p>変わらず。</p> <h3 id="my.cnf 等"><a href="#my.cnf+%E7%AD%89">my.cnf 等</a></h3> <p>こちらも変わらず。</p> <h3 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h3> <p><a href="https://crieit.now.sh/upload_images/d64288e5b382b9fe2564274e8237a20c6212500befe90.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/d64288e5b382b9fe2564274e8237a20c6212500befe90.jpg?mw=700" alt="新しい設定方法で投稿した場合の挙動" /></a></p> <p>新しい方法で設定した Docker 環境上に先程と同様 WordPress をインストールして記事を投稿すると、無事投稿が公開されました。</p> <p>このとき、 <code>wp_posts</code> のテーブルを直接見ると、 <code>post_date</code>, <code>post_modified</code> は同じ日時、 <code>post_date_gmt</code>, <code>post_modified_gmt</code> は -9時間の日時になっていました。</p> <p>やはりここがおかしかったようです。</p> <h2 id="続・検証"><a href="#%E7%B6%9A%E3%83%BB%E6%A4%9C%E8%A8%BC">続・検証</a></h2> <p>さて、それではこの時刻の狂いはどこに起因しているのでしょうか。</p> <p><a href="https://crieit.now.sh/upload_images/67aea8dcc499e2cd3be8f9a4698e5de1621250140823c.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/67aea8dcc499e2cd3be8f9a4698e5de1621250140823c.jpg?mw=700" alt="Webサーバのみ新しい設定方法で投稿した場合の挙動" /></a></p> <p>Webサーバの Dockerコンテナ のみ今回の新しい方法で localtime を設定した場合。OKですね。</p> <p><a href="https://crieit.now.sh/upload_images/35de93c1057c97f109f3c8e152c7ec526212501e5c450.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/35de93c1057c97f109f3c8e152c7ec526212501e5c450.jpg?mw=700" alt="DBサーバのみ新しい設定方法で投稿した場合の挙動" /></a></p> <p>DBサーバの Dockerコンテナ のみ今回の新しい方法で localtime を設定した場合。NGです。</p> <p>ということで、原因は Webサーバ 側にありそうです。</p> <h3 id="Webサーバでの date"><a href="#Web%E3%82%B5%E3%83%BC%E3%83%90%E3%81%A7%E3%81%AE+date">Webサーバでの date</a></h3> <p>ただ、 Webサーバ のコンテナで <code>date</code> コマンドを打っても日時は正しい日時が返ってくるのですよね。</p> <h4 id="設定方法が未変更の状態の Webサーバ コンテナ"><a href="#%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95%E3%81%8C%E6%9C%AA%E5%A4%89%E6%9B%B4%E3%81%AE%E7%8A%B6%E6%85%8B%E3%81%AE+Web%E3%82%B5%E3%83%BC%E3%83%90+%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A">設定方法が未変更の状態の Webサーバ コンテナ</a></h4> <pre><code class="bash"># php -r 'echo date_default_timezone_get() . PHP_EOL; echo date(&quot;y-m-d H:i:s&quot;) . PHP_EOL;' Asia/Tokyo 22-02-13 19:06:21 # date Thu Feb 13 19:06:28 JST 2022 </code></pre> <h4 id="設定方法を変更した状態の Webサーバ コンテナ"><a href="#%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%9F%E7%8A%B6%E6%85%8B%E3%81%AE+Web%E3%82%B5%E3%83%BC%E3%83%90+%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A">設定方法を変更した状態の Webサーバ コンテナ</a></h4> <pre><code class="bash"># php -r 'echo date_default_timezone_get() . PHP_EOL; echo date(&quot;y-m-d H:i:s&quot;) . PHP_EOL;' Asia/Tokyo 22-02-13 19:16:50 # date 2022年 2月 13日 日曜日 19:16:56 JST </code></pre> <p>ご覧の通り時刻は正常……ってあれ、確かに日時は正常ですが、出力フォーマットが異なっています。</p> <p>どうやら今までの設定変更ではやはり不完全な部分があるようです。どこが、というところまでは追い切れていないですが、ここまでの検証で確かに今までの設定方法では宜しくないであろう、ということが断片的に表われているので、ここは大人しく新しい設定方法に変更していった方が良さそうです。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/rururu_kenken/items/972314402d588e073d40">Dockerコンテナのタイムゾーン変更方法 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/jeffi7/items/9d4c85cf049644f711b8">Docker で \/etc\/localtime をホストに volume マウントしてハマった話 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://saito-shion-technology.hatenablog.jp/entry/2020/02/27/115040">Docker : コンテナのタイムゾーンを変更する - saito-shion technology diary</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/polarbear08/items/e5c00869c7566db5f7b8">CentOS7・CentOS8のDockerコンテナの日本語化および日本時間設定 - Qiita</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/18121 2022-02-23T00:12:52+09:00 2022-02-23T00:12:52+09:00 https://crieit.net/posts/error-at-install-mysql-community-server-import-rpm-pgp-key-20220223 Docker で MySQL の community版をインストールしようとした際に Failing package is: ... エラー <p>Docker の MySQL コンテナを構築する Dockerfile を走らせようとしたところ、</p> <blockquote> <p>The GPG keys listed for the "MySQL 8.0 Community Server" repository are already installed but they are not correct for this package.</p> </blockquote> <p>や</p> <blockquote> <p>Public key for mysql-community-client-8.0.28-1.el8.x86_64.rpm is not installed. Failing package is: mysql-community-client-8.0.28-1.el8.x86_64</p> </blockquote> <p>というエラーが発生してしまったので対処。</p> <h3 id="改修前の Dockerfile"><a href="#%E6%94%B9%E4%BF%AE%E5%89%8D%E3%81%AE+Dockerfile">改修前の Dockerfile</a></h3> <pre><code class="dockerfile">RUN dnf -y localinstall https://dev.mysql.com/get/mysql80-community-release-el8-2.noarch.rpm </code></pre> <p>コミュニティ版の MySQL8 をインストールしようとしています。</p> <h3 id="改修後の Dockerfile"><a href="#%E6%94%B9%E4%BF%AE%E5%BE%8C%E3%81%AE+Dockerfile">改修後の Dockerfile</a></h3> <pre><code class="dockerfile">RUN rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 && dnf -y localinstall https://dev.mysql.com/get/mysql80-community-release-el8-2.noarch.rpm </code></pre> <p>エラー文で検索したところ、</p> <pre><code class="bash">rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 </code></pre> <p>を追加すると良い、という記事を見かけたので追加したところ、エラーが発生しなくなったのでこれで対処。</p> <h3 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://support.cpanel.net/hc/en-us/articles/4419382481815-MySQL-GPG-keys-expired-preventing-installation-upgrade-of-MySQL-packages-from-the-official-repository-">MySQL GPG keys expired, preventing installation\/upgrade of MySQL packages from the official repository. – cPanel</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://support.cpanel.net/hc/en-us/articles/4419382481815-Installer-fails-due-to-The-GPG-keys-listed-for-the-MySQL-repository-are-already-installed-but-they-are-not-correct-for-this-package-">MySQL GPG keys expired, preventing installation\/upgrade of MySQL packages from the official repository. – cPanel</a></li> </ul> <p>URLは異なりますがどちらも同じ内容の模様。</p> arm-band tag:crieit.net,2005:PublicArticle/17932 2022-01-12T00:06:20+09:00 2022-01-12T00:06:20+09:00 https://crieit.net/posts/centos-onelinear-ternary-and-compoare-operator-20220112 CentOS の bash で比較演算と三項演算子的な処理を使って変数に代入する値を分岐するワンライナー <p><a href="https://crieit.net/posts/diverting-date-as-args-in-dockerfile-20211230">Dockerfile 内でコンテナの時刻を変数として流用し、年に対応した rpmパッケージ の GPG署名 をインストールする</a>で試験した内容の続きとなります。</p> <ul> <li><code>http://rpms.famillecollet.com/RPM-GPG-KEY-remi2021</code>: OK</li> <li><code>http://rpms.famillecollet.com/RPM-GPG-KEY-remi2022</code>: Not Found.</li> </ul> <p>remiリポジトリのGPG署名が2022年版が存在しないので、条件分岐で2021を最大値とするように処理を書いてみました。</p> <h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2> <pre><code class="bash"># date 2022年 1月 11日 火曜日 20:42:53 JST </code></pre> <p>今回の検証環境はこのような表示がされる CentOS の日本語版の環境。</p> <pre><code class="bash"># NOWYEAR=$(sudo date | sudo awk 'END{print $1}' | sudo sed -e 's/年//g') && [ ${NOWYEAR} -gt 2021 ] && ALTERYEAR=2021 || ALTERYEAR=${NOWYEAR} && echo ${ALTERYEAR} 2021 </code></pre> <p>早速完成したワンライナーですが、このようになりました。</p> <h2 id="説明"><a href="#%E8%AA%AC%E6%98%8E">説明</a></h2> <p>わりと複雑になってしまったので順番に読んでいきます。</p> <pre><code class="bash">NOWYEAR=$(sudo date | sudo awk 'END{print $1}' | sudo sed -e 's/年//g') \ # date コマンドの結果から、 awk でスペース区切り1つ目の値(2022年) を抽出し、 `sed -e` で`年`を落とす。結果、`2022`が得られる && [ ${NOWYEAR} -gt 2021 ] && ALTERYEAR=2021 || ALTERYEAR=${NOWYEAR} \ # 三項演算子的な処理。 {コマンドとして実行可能な式} && {前述式が true の場合の処理} || {前述式が false の場合の処理} 。今回は得られた現在の年が2021年以降ならば2021を変数に代入、そうでなければ現在の年を変数代入 && echo ${ALTERYEAR} # 上の三項演算子的な処理で代入された変数の値を echo </code></pre> <p>こんな感じです。</p> <pre><code class="dockerfile">RUN MELUSINE=$(sudo date | sudo awk 'END{print $6}') \ && [ ${NOWYEAR} -gt 2021 ] && ALTERYEAR=2021 || ALTERYEAR=${NOWYEAR} \ && rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-8.rpm \ && rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi${ALTERYEAR} </code></pre> <p>今回はこんな感じで <code>http://rpms.famillecollet.com/RPM-GPG-KEY-remi2021</code> か、 <code>http://rpms.famillecollet.com/RPM-GPG-KEY-remi{2020以下}</code> かを読み込む分岐に。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.pmi-sfbac.org/arithmetic-comparison/">【Shellスクリプト】演算子「算術演算子」「比較演算子」について! | Beエンジニア</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://eng-entrance.com/linux-shellscript-replacement">【Linux】シェルスクリプトによる文字列処理:置換や削除をする方法</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17901 2021-12-30T01:05:47+09:00 2021-12-30T01:07:46+09:00 https://crieit.net/posts/diverting-date-as-args-in-dockerfile-20211230 Dockerfile 内でコンテナの時刻を変数として流用し、年に対応した rpmパッケージ の GPG署名 をインストールする <p>Dockerコンテナ をビルドする際にコンテナ内の時刻(年)を他のコマンドに流用したくなりました。その方法をいくつか試したのでメモしておきます。</p> <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>AlmaLinux で PHP7.4系 をインストールする際に Remiリポジトリ からインストールしようとしました。</p> <pre><code class="dockerfile">RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-8.rpm && \ rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi2021 # disable default module RUN dnf module reset -y php # install php 7.4 RUN dnf module install -y php:remi-7.4 </code></pre> <p><code>rpm</code> を使用して Remiリポジトリ をインストールしています。</p> <p><code>rpm</code> ではパッケージインストールではパッケージが破損していないか、改ざんされていないかをチェックするために GPG署名 を用いています。</p> <p>その公開鍵の取得も、 Remiリポジトリ のインストールと同時に行っています。</p> <pre><code class="dockerfile">RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-8.rpm && \ rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi2021 </code></pre> <p>ここでふと思ったのは、URLに年が入っていること。2022年になったら</p> <pre><code class="dockerfile">RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-8.rpm && \ rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi2022 </code></pre> <p>に変えたい。かといってそれを毎年手動で更新するのは面倒なので、自動化したい。</p> <p>であれば、 <code>date</code> コマンドの値を <code>awk</code> に通すなどして年だけ取り出し、それを上述コマンドに流用できないか、と。</p> <h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2> <p>まずは AlmaLinux のコンテナをビルド・起動します。</p> <pre><code class="bash">docker run --name yeartest -it almalinux:8 /bin/bash </code></pre> <pre><code class="bash"># \cp -pf /usr/share/zoneinfo/Japan /etc/localtime ## タイムゾーン変更 # dnf -y update && yum -y install sudo epel-release ## 略 </code></pre> <p>パッケージを入れたり前準備。</p> <h3 id="date から年のみ取り出す"><a href="#date+%E3%81%8B%E3%82%89%E5%B9%B4%E3%81%AE%E3%81%BF%E5%8F%96%E3%82%8A%E5%87%BA%E3%81%99">date から年のみ取り出す</a></h3> <pre><code class="bash"># date Wed Dec 29 22:28:18 JST 2021 </code></pre> <p>普通に <code>date</code> を叩きます。ふむ、6番目ですね……。</p> <pre><code class="bash"># sudo date | sudo awk '{print $6}' 2021 </code></pre> <p>そこでパイプで繋いで <code>awk</code> に渡します。無事、年のみを取り出せました。</p> <h3 id="rpm の GPG署名 について"><a href="#rpm+%E3%81%AE+GPG%E7%BD%B2%E5%90%8D+%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">rpm の GPG署名 について</a></h3> <p>一応インポートされている GPG署名 について確認しておきます。</p> <pre><code class="bash"># rpm -qa 'gpg-pubkey*' gpg-pubkey-3abb34f8-5ffd890e </code></pre> <p>まずデフォルトの状態。1つのみインポートされていますね。</p> <pre><code class="bash"># rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi2021 # rpm -qa 'gpg-pubkey*' gpg-pubkey-3abb34f8-5ffd890e gpg-pubkey-478f8947-5ff329c5 </code></pre> <p>次に <code>RPM-GPG-KEY-remi2021</code> をインポートします。増えました。</p> <pre><code class="bash"># rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi # rpm -qa 'gpg-pubkey*' gpg-pubkey-3abb34f8-5ffd890e gpg-pubkey-478f8947-5ff329c5 gpg-pubkey-00f97f56-467e318a </code></pre> <p>さらに <code>RPM-GPG-KEY-remi</code> をインポートすると増えました。</p> <h2 id="検証2"><a href="#%E6%A4%9C%E8%A8%BC2">検証2</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/test-docker-tychedight">Tychedight</a></li> </ul> <p>以上を踏まえて、 Docker Compose からの Dockerfile ビルドで試験。</p> <pre><code class="dockerfile">FROM almalinux:8 RUN \cp -pf /usr/share/zoneinfo/Japan /etc/localtime RUN dnf -y update && yum -y install \ sudo \ epel-release RUN mkdir /home/temp/ # パターン1 RUN GEOFFROY=$(sudo date | sudo awk 'END{print $6}') \ && sudo echo ${GEOFFROY} >> /home/temp/geoffroy.txt # パターン2 RUN FROMONT=$(sudo date | sudo awk 'END{print $6}') RUN sudo echo ${FROMONT} >> /home/temp/fromont.txt # パターン3 RUN sudo echo \ | sudo date \ | sudo awk 'END{print $6}' \ >> /home/temp/carillon.txt </code></pre> <p>一応3つパターンを試してみます。さあ、それぞれのファイルには何が出力されるのか……。</p> <pre><code class="dockerfile"># パターン1 RUN GEOFFROY=$(sudo date | sudo awk 'END{print $6}') \ && sudo echo ${GEOFFROY} >> /home/temp/geoffroy.txt # 2021 # パターン2 RUN FROMONT=$(sudo date | sudo awk 'END{print $6}') RUN sudo echo ${FROMONT} >> /home/temp/fromont.txt # # パターン3 RUN sudo echo \ | sudo date \ | sudo awk 'END{print $6}' \ >> /home/temp/carillon.txt # 2021 </code></pre> <p>結果、意図した出力になったのは1つ目と3つ目のパターンでした。 <code>RUN</code> ごとにコンテナが変わるとのことなので2は望み薄だと思っていましたが……。</p> <p>そこで、パターン1を使って次のように組んでみます。</p> <pre><code class="dockerfile">FROM almalinux:8 RUN \cp -pf /usr/share/zoneinfo/Japan /etc/localtime RUN dnf -y update && yum -y install \ sudo \ epel-release RUN mkdir /home/temp/ # args RUN MELUSINE=$(sudo date | sudo awk 'END{print $6}') \ && rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-8.rpm \ && rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi${MELUSINE} </code></pre> <p>これでビルド・起動したコンテナに bash で入って確認。</p> <pre><code class="bash"># rpm -qa 'gpg-pubkey*' gpg-pubkey-3abb34f8-5ffd890e gpg-pubkey-478f8947-5ff329c5 </code></pre> <p>内容的にデフォルトと2021の公開鍵が入っているように見えます。</p> <pre><code class="bash"># rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi # rpm -qa 'gpg-pubkey*' gpg-pubkey-3abb34f8-5ffd890e gpg-pubkey-478f8947-5ff329c5 gpg-pubkey-00f97f56-467e318a </code></pre> <p>手動で <code>RPM-GPG-KEY-remi</code> を入れると増えました。</p> <pre><code class="bash"># rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi2021 # rpm -qa 'gpg-pubkey*' gpg-pubkey-3abb34f8-5ffd890e gpg-pubkey-478f8947-5ff329c5 gpg-pubkey-00f97f56-467e318a </code></pre> <p>ついでに手動で <code>RPM-GPG-KEY-remi2021</code> を入れようとしましたが、数は増えませんでした。先のコードで <code>RPM-GPG-KEY-remi2021</code> がインストールできていることが確認できました。OKです。</p> <h2 id="余談"><a href="#%E4%BD%99%E8%AB%87">余談</a></h2> <p>実は上述の通り年指定のない <code>http://rpms.famillecollet.com/RPM-GPG-KEY-remi</code> があるので、それを入れてしまえば終わりのような気もするのですが……折角なのでチャレンジしてみた次第です。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="PHP インストール"><a href="#PHP+%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">PHP インストール</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.tsuda1.com/%E6%9C%AA%E5%88%86%E9%A1%9E/php%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/">PHPインストール PHP7.4 CentOS8 | AlmaLinux 自宅サーバ</a></li> </ul> <p>もしかして、そもそもいらない……?</p> <h3 id="rpm と GPG署名"><a href="#rpm+%E3%81%A8+GPG%E7%BD%B2%E5%90%8D">rpm と GPG署名</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/deployment_guide/s1-check-rpm-sig">B.3. パッケージの署名確認 Red Hat Enterprise Linux 6 | Red Hat Customer Portal</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/aosho235/items/9ba95b6b8fb1ce8ac580">CentOS 7 インストールされている全パッケージのrpmをダウンロードする - Qiita</a> <ul> <li>インポートされた公開鍵の確認</li> </ul></li> <li>参考: <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.kakiro-web.com/linux/centos6-remi-install.html">CentOS6.7 64bitのyumリポジトリにRemiを追加 - Kakiro-Web カキローウェブ</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://pentan.info/server/linux/yum/remi.html">Remi 基本リポジトリで提供されていないパッケージのyumインストール - [yum/Linux [Red Hat/CentOSなど]] ぺんたん info</a></li> </ul></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17898 2021-12-29T00:16:11+09:00 2021-12-29T00:17:49+09:00 https://crieit.net/posts/test-centos8-lamp-for-almalinux-in-docker-20211229 (Docker) Almalinux を見据えて CentOS8 での環境構築を試験してみる <p>手前味噌で恐縮ですが、自作の LAMP環境 を検証する Docker Compose について。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/docker_compose_ambergrease">GitHub - arm-band/docker_compose_ambergrease</a></li> </ul> <p>イメージを CentOS7 ベースで構築しているので、いずれは AlmaLinux なり Rocky Linux なりに移行しなければならないことは分かっていました。</p> <p>そこで、その以降を見据えて残り数日の命の CentOS8 で試験してみることにしました。なぜ AlmaLinux や Rocky Linux ではなくわざわざ CentOS8 かというと、いきなりそれらのOSに飛びついて何らかの不具合が発生したときに原因の切り分けで苦労するならば、まだ同じシリーズで差分が少ない (と想定される) CentOS8 で試験して、問題なければ次に進もう、という段階的な試験を想定したためです。</p> <h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2> <pre><code class="bash">docker run --name php7_cent8 -it centos:centos8 /bin/bash </code></pre> <p>まずはイメージを取得し、 bash に入ります。</p> <h3 id="Apache + PHP"><a href="#Apache+%2B+PHP">Apache + PHP</a></h3> <p>最初は Apache + PHP 。こちらについては、以前 <a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2020/02/23/centos8-lamp-install-note/">CentOS8 をインストールして遊んだとき</a>にremiリポジトリの入り方が CentOS7 とは異なることが分かっていたので、多少手を加える必要があるだろう、と踏んでいました。</p> <pre><code class="bash"># \cp -pf /usr/share/zoneinfo/Japan /etc/localtime # </code></pre> <p>これは問題なし。</p> <pre><code class="bash"># dnf -y update && yum -y install epel-release sudo less iproute httpd-devel zip unzip openssl mod_ssl ## 略 Installed: apr-1.6.3-12.el8.x86_64 apr-devel-1.6.3-12.el8.x86_64 apr-util-1.6.1-6.el8.x86_64 apr-util-bdb-1.6.1-6.el8.x86_64 apr-util-devel-1.6.1-6.el8.x86_64 apr-util-openssl-1.6.1-6.el8.x86_64 brotli-1.0.6-3.el8.x86_64 centos-logos-httpd-85.8-2.el8.noarch cyrus-sasl-2.1.27-5.el8.x86_64 cyrus-sasl-devel-2.1.27-5.el8.x86_64 epel-release-8-11.el8.noarch expat-devel-2.2.5-4.el8.x86_64 groff-base-1.22.3-18.el8.x86_64 httpd-2.4.37-43.module_el8.5.0+1022+b541f3b1.x86_64 httpd-devel-2.4.37-43.module_el8.5.0+1022+b541f3b1.x86_64 httpd-filesystem-2.4.37-43.module_el8.5.0+1022+b541f3b1.noarch httpd-tools-2.4.37-43.module_el8.5.0+1022+b541f3b1.x86_64 libdb-devel-5.3.28-42.el8_4.x86_64 libpath_utils-0.2.1-39.el8.x86_64 libpkgconf-1.4.2-1.el8.x86_64 libtalloc-2.3.2-1.el8.x86_64 mailcap-2.1.48-3.el8.noarch mod_http2-1.15.7-3.module_el8.4.0+778+c970deab.x86_64 mod_ssl-1:2.4.37-43.module_el8.5.0+1022+b541f3b1.x86_64 ncurses-6.1-9.20180224.el8.x86_64 openldap-devel-2.4.46-18.el8.x86_64 perl-Carp-1.42-396.el8.noarch perl-Data-Dumper-2.167-399.el8.x86_64 perl-Digest-1.17-395.el8.noarch perl-Digest-MD5-2.55-396.el8.x86_64 perl-Encode-4:2.97-3.el8.x86_64 perl-Errno-1.28-420.el8.x86_64 perl-Exporter-5.72-396.el8.noarch perl-File-Path-2.15-2.el8.noarch perl-File-Temp-0.230.600-1.el8.noarch perl-Getopt-Long-1:2.50-4.el8.noarch perl-HTTP-Tiny-0.074-1.el8.noarch perl-IO-1.38-420.el8.x86_64 perl-IO-Socket-IP-0.39-5.el8.noarch perl-IO-Socket-SSL-2.066-4.module_el8.3.0+410+ff426aa3.noarch perl-MIME-Base64-3.15-396.el8.x86_64 perl-Mozilla-CA-20160104-7.module_el8.3.0+416+dee7bcef.noarch perl-Net-SSLeay-1.88-1.module_el8.3.0+410+ff426aa3.x86_64 perl-PathTools-3.74-1.el8.x86_64 perl-Pod-Escapes-1:1.07-395.el8.noarch perl-Pod-Perldoc-3.28-396.el8.noarch perl-Pod-Simple-1:3.35-395.el8.noarch perl-Pod-Usage-4:1.69-395.el8.noarch perl-Scalar-List-Utils-3:1.49-2.el8.x86_64 perl-Socket-4:2.027-3.el8.x86_64 perl-Storable-1:3.11-3.el8.x86_64 perl-Term-ANSIColor-4.06-396.el8.noarch perl-Term-Cap-1.17-395.el8.noarch perl-Text-ParseWords-3.30-395.el8.noarch perl-Text-Tabs+Wrap-2013.0523-395.el8.noarch perl-Time-Local-1:1.280-1.el8.noarch perl-URI-1.73-3.el8.noarch perl-Unicode-Normalize-1.25-396.el8.x86_64 perl-constant-1.33-396.el8.noarch perl-interpreter-4:5.26.3-420.el8.x86_64 perl-libnet-3.11-3.el8.noarch perl-libs-4:5.26.3-420.el8.x86_64 perl-macros-4:5.26.3-420.el8.x86_64 perl-parent-1:0.237-1.el8.noarch perl-podlators-4.11-1.el8.noarch perl-threads-1:2.21-2.el8.x86_64 perl-threads-shared-1.58-2.el8.x86_64 pkgconf-1.4.2-1.el8.x86_64 pkgconf-m4-1.4.2-1.el8.noarch pkgconf-pkg-config-1.4.2-1.el8.x86_64 sscg-2.3.3-14.el8.x86_64 sudo-1.8.29-7.el8_4.1.x86_64 unzip-6.0-45.el8_4.x86_64 zip-3.0-23.el8.x86_64 Complete! </code></pre> <p>OK。</p> <pre><code class="bash"># dnf -y upgrade ## 略 Upgraded: epel-release-8-13.el8.noarch Complete! </code></pre> <p>特に大きな差分もなさそうです。OK。</p> <h3 id="remiリポジトリ"><a href="#remi%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA">remiリポジトリ</a></h3> <pre><code class="bash"># rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-8.rpm Retrieving http://rpms.famillecollet.com/enterprise/remi-release-8.rpm warning: /var/tmp/rpm-tmp.hlvLxe: Header V4 RSA/SHA256 Signature, key ID 5f11735a: NOKEY Verifying... ################################# [100%] Preparing... ################################# [100%] Updating / installing... 1:remi-release-8.5-2.el8.remi ################################# [100%] # rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi2021 # </code></pre> <p>OK。 CentOS8 用のリポジトリに切り替えました。鍵についてはすぐ <code>RPM-GPG-KEY-remi2022</code> にしなければならないでしょうけど。</p> <h4 id="dnf"><a href="#dnf">dnf</a></h4> <pre><code class="bash"># dnf config-manager --enable remi && dnf config-manager --enable remi-php74 No such command: config-manager. Please use /usr/bin/dnf --help It could be a DNF plugin command, try: "dnf install 'dnf-command(config-manager)'" </code></pre> <p><code>remi-php74</code> に指定で躓くかと思いきや、そもそも <code>config-manager</code> がない、と?</p> <p>元々は <code>yum-config-manager</code> だったのですが、 CentOS8 であれば <code>dnf</code> ベースの方が良いだろう、ということで置き換えてはみましたが、ダメですか……。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://blog.trippyboy.com/2021/terraform/almalinux%E3%81%ABterraform%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92yum%E3%81%A7%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B%E3%81%AE%E5%B7%BB/">Almalinuxにterraformコマンドをyumで導入するの巻 - TrippyBoyの愉快な日々</a></li> </ul> <p>こちらより <code>dnf install -y dnf-plugins-core</code> してみます。</p> <pre><code class="bash"># dnf install dnf-plugins-core ## 略 Installed: dbus-glib-0.110-2.el8.x86_64 dnf-plugins-core-4.0.21-3.el8.noarch python3-dateutil-1:2.6.1-6.el8.noarch python3-dbus-1.2.4-15.el8.x86_64 python3-dnf-plugins-core-4.0.21-3.el8.noarch python3-six-1.11.0-8.el8.noarch Complete! </code></pre> <p>OK。</p> <h4 id="remi + PHP"><a href="#remi+%2B+PHP">remi + PHP</a></h4> <pre><code class="bash"># dnf config-manager --enable remi && dnf config-manager --enable remi-php74 Error: No matching repo to modify: remi-php74. </code></pre> <p>……やはり <code>remi-php74</code> で引っかかりましたか。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://mebee.info/2020/03/12/post-7365/">CentOs8 php7.4をインストールする | mebee</a></li> </ul> <p>……想定していたものとは少し違うやり方ですが、試してみましょう。</p> <pre><code class="bash"># dnf module reset php ## 略 Remi's RPM repository for Enterprise Linux 8 - x86_64 598 kB/s | 3.9 MB 00:06 Last metadata expiration check: 0:00:03 ago on DDD dd mmm yyyy hh:ii:ss AM UTC. Dependencies resolved. Nothing to do. Complete! </code></pre> <p>OK。</p> <pre><code class="bash"># dnf module install -y php:remi-7.4 ## 略 Installed: libedit-3.1-23.20170329cvs.el8.x86_64 libxslt-1.1.32-6.el8.x86_64 nginx-filesystem-1:1.14.1-9.module_el8.0.0+184+e34fea82.noarch oniguruma5php-6.9.7.1-1.el8.remi.x86_64 php-cli-7.4.27-1.el8.remi.x86_64 php-common-7.4.27-1.el8.remi.x86_64 php-fpm-7.4.27-1.el8.remi.x86_64 php-json-7.4.27-1.el8.remi.x86_64 php-mbstring-7.4.27-1.el8.remi.x86_64 php-xml-7.4.27-1.el8.remi.x86_64 Complete! # php --version PHP 7.4.27 (cli) (built: Dec 14 2021 17:17:06) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies </code></pre> <p>OK。入りましたね。これに従い該当箇所を書き換えます。</p> <pre><code class="dockerfile"># enable repository remi & remi-php74 #RUN dnf config-manager --enable remi && dnf config-manager --enable remi-php74 # disable default module RUN dnf module reset -y php RUN dnf module install -y php:remi-7.4 ## 略 # disable repository remi & remi-php74 #RUN dnf config-manager --disable remi && dnf config-manager --disable remi-php74 </code></pre> <p><code>config-manager</code> によるリポジトリ使用のオン・オフの切り替えを削除しました。</p> <pre><code class="bash"># dnf -y install php php-devel php-pdo php-mysqlnd php-mbstring php-gd php-pear php-pecl-apc-devel zlib-devel php-xml php-mcrypt php-pecl-xdebug ## 略 Installed: autoconf-2.69-29.el8.noarch automake-1.16.1-7.el8.noarch cmake-filesystem-3.20.2-4.el8.x86_64 cpp-8.5.0-4.el8_5.x86_64 dejavu-fonts-common-2.35-7.el8.noarch dejavu-sans-fonts-2.35-7.el8.noarch emacs-filesystem-1:26.1-7.el8.noarch fontconfig-2.13.1-4.el8.x86_64 fontpackages-filesystem-1.44-22.el8.noarch freetype-2.9.1-4.el8_3.1.x86_64 fribidi-1.0.4-8.el8.x86_64 gcc-8.5.0-4.el8_5.x86_64 gcc-c++-8.5.0-4.el8_5.x86_64 gd3php-2.3.3-4.el8.remi.x86_64 glibc-devel-2.28-164.el8.x86_64 glibc-headers-2.28-164.el8.x86_64 graphite2-1.3.10-10.el8.x86_64 harfbuzz-1.7.5-3.el8.x86_64 isl-0.16.1-6.el8.x86_64 jbigkit-libs-2.1-14.el8.x86_64 kernel-headers-4.18.0-348.2.1.el8_5.x86_64 keyutils-libs-devel-1.5.10-9.el8.x86_64 krb5-devel-1.18.2-14.el8.x86_64 libX11-1.6.8-5.el8.x86_64 libX11-common-1.6.8-5.el8.noarch libXau-1.0.9-3.el8.x86_64 libXpm-3.5.12-8.el8.x86_64 libcom_err-devel-1.45.6-2.el8.x86_64 libimagequant-2.12.5-1.el8.x86_64 libjpeg-turbo-1.5.3-12.el8.x86_64 libkadm5-1.18.2-14.el8.x86_64 libmcrypt-2.5.8-26.el8.x86_64 libmpc-1.1.0-9.1.el8.x86_64 libpng-2:1.6.34-5.el8.x86_64 libraqm-0.7.0-4.el8.x86_64 libselinux-devel-2.9-5.el8.x86_64 libsepol-devel-2.9-3.el8.x86_64 libsodium-1.0.18-2.el8.x86_64 libstdc++-devel-8.5.0-4.el8_5.x86_64 libtiff-4.0.9-20.el8.x86_64 libtool-2.4.6-25.el8.x86_64 libverto-devel-0.3.0-5.el8.x86_64 libwebp-1.0.0-5.el8.x86_64 libxcb-1.13.1-1.el8.x86_64 libxcrypt-devel-4.1.1-6.el8.x86_64 libxml2-devel-2.9.7-9.el8_4.2.x86_64 m4-1.4.18-7.el8.x86_64 make-1:4.2.1-10.el8.x86_64 openssl-devel-1:1.1.1k-5.el8_5.x86_64 pcre2-devel-10.32-2.el8.x86_64 pcre2-utf16-10.32-2.el8.x86_64 pcre2-utf32-10.32-2.el8.x86_64 perl-Thread-Queue-3.13-1.el8.noarch php-7.4.27-1.el8.remi.x86_64 php-devel-7.4.27-1.el8.remi.x86_64 php-fedora-autoloader-1.0.1-2.el8.remi.noarch php-gd-7.4.27-1.el8.remi.x86_64 php-mysqlnd-7.4.27-1.el8.remi.x86_64 php-opcache-7.4.27-1.el8.remi.x86_64 php-pdo-7.4.27-1.el8.remi.x86_64 php-pear-1:1.10.13-1.el8.remi.noarch php-pecl-apcu-5.1.21-1.el8.remi.7.4.x86_64 php-pecl-apcu-devel-5.1.21-1.el8.remi.7.4.x86_64 php-pecl-mcrypt-1.0.4-1.el8.remi.7.4.x86_64 php-pecl-xdebug-2.9.8-1.el8.remi.7.4.x86_64 php-process-7.4.27-1.el8.remi.x86_64 php-sodium-7.4.27-1.el8.remi.x86_64 xz-devel-5.2.4-3.el8.x86_64 zlib-devel-1.2.11-17.el8.x86_64 Complete! </code></pre> <p>OK。</p> <pre><code class="bash"># php -r &quot;copy('https://getcomposer.org/installer', 'composer-setup.php');&quot; && php composer-setup.php && php -r &quot;unlink('composer-setup.php');&quot; && mv composer.phar /usr/local/bin/composer All settings correct for using Composer Downloading... Composer (version 2.2.1) successfully installed to: /etc/yum.repos.d/composer.phar Use it: php composer.phar # composer --version Composer version 2.2.1 2021-12-22 22:21:31 </code></pre> <p>Composer も入りました。</p> <pre><code class="bash"># mkdir /var/log/php # chown apache /var/log/php # chmod 755 /var/log/php # mkdir -p /etc/ssl/private </code></pre> <p>まあこの辺りは普通に。</p> <h3 id="SSL"><a href="#SSL">SSL</a></h3> <pre><code class="bash"># openssl req -new -newkey rsa:2048 -nodes -out /etc/ssl/private/server.csr -keyout /etc/ssl/private/server.key -subj &quot;/C=/ST=/L=/O=/OU=/CN=*.lvh.me&quot; ## 略 # openssl x509 -days 365 -req -signkey /etc/ssl/private/server.key -in /etc/ssl/private/server.csr -out /etc/ssl/private/server.crt Signature ok subject=CN = *.lvh.me Getting Private key </code></pre> <p>OK。</p> <h3 id="Apache の設定ファイル"><a href="#Apache+%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB">Apache の設定ファイル</a></h3> <h4 id="ssl.conf"><a href="#ssl.conf">ssl.conf</a></h4> <pre><code class="bash"># cat /etc/httpd/conf.d/ssl.conf ## 略 </code></pre> <p>表示させたSSL用の設定を現行のものと差し替えます。ただし、現行の設定をなるべく引き継ぐように。これは他の設定ファイルも同様です。</p> <pre><code class="conf">- SSLRandomSeed startup file:/dev/urandom 256 - SSLRandomSeed connect builtin - SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA </code></pre> <p>現行にあったこれらの行は削除。</p> <pre><code class="conf">+ SSLHonorCipherOrder on </code></pre> <p>これは新しく追加されていました。</p> <pre><code class="conf">SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 </code></pre> <p>プロトコルについては念のため現行の設定を引き継ぎ。流石にもう SSLv2 なんて存在しないでしょうけど……。</p> <pre><code class="conf">- <Files ~ "\.(cgi|shtml|phtml|php3?)$"> + <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars - </Files> + </FilesMatch> </code></pre> <p>微妙にディレクティブの表現が変わっていますが、影響はなさそうなので変更を受け入れます。</p> <h4 id="php.conf"><a href="#php.conf">php.conf</a></h4> <pre><code class="bash"># cat /etc/httpd/conf.d/php.conf ## 略 # Redirect to local php-fpm if mod_php (5 or 7) is not available <IfModule !mod_php5.c> <IfModule !mod_php7.c> # Enable http authorization headers SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1 <FilesMatch \.(php|phar)$> SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost" </FilesMatch> </IfModule> </IfModule> </code></pre> <p>こちらは最後の部分に追記がありますね。これはそのまま受け入れ。</p> <h4 id="php.ini"><a href="#php.ini">php.ini</a></h4> <pre><code class="bash"># cat /etc/php.ini ## 略 </code></pre> <p>こちらも設定を引き継ぎ、といっても現行の設定と変更点はなく(自前の設定を引き継いだ) 差分としてはコメントの文字列くらい。</p> <h3 id="AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message"><a href="#AH00558%3A+httpd%3A+Could+not+reliably+determine+the+server%27s+fully+qualified+domain+name%2C+using+192.0.2.1.+Set+the+%27ServerName%27+directive+globally+to+suppress+this+message">AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message</a></h3> <p>Apache を起動しようとしたところ、</p> <blockquote> <p>AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message</p> </blockquote> <p>のエラーメッセージがログに記録されて起動してこない現象に遭遇。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/sachiko-kame/items/a6deebbad207d627b598">[Docker]AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using ***.***.*.*. Set the 'ServerName' directive globally to suppress this message - Qiita</a></li> </ul> <p>そういえば元々の Dockerfile には記述していましたが、 <code>httpd.conf</code> への追記をしていませんでした。</p> <pre><code class="bash">echo ServerName www.example.com:80 >> /etc/httpd/conf/httpd.conf </code></pre> <p>これでOK。</p> <pre><code class="bash"># httpd -v Server version: Apache/2.4.37 (centos) Server built: Nov 12 2021 04:57:27 </code></pre> <p>バージョンも拾えました。</p> <h3 id="(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed"><a href="#%282%29No+such+file+or+directory%3A+AH02454%3A+FCGI%3A+attempt+to+connect+to+Unix+domain+socket+%2Frun%2Fphp-fpm%2Fwww.sock+%28%2A%29+failed">(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed</a></h3> <p>これで Apache も起動してきたのでブラウザで表示確認、ということで <code>phpinfo()</code> でも表示させようかとファイルを用意して <code>curl</code> してみると……</p> <blockquote> <p>Service Unavailable</p> <p>The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.</p> </blockquote> <p>503エラーが出てしまいました。</p> <blockquote> <p>(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed</p> </blockquote> <p>Apache のエラーログには上述のログが記録されていました。</p> <p>今までとは異なる方法で PHP をインストールしたら、どうやら php-fpm (CGIモード) で動作しようとしてしまっているようです。</p> <p>今回の環境ではCGI版かモジュール版かはあまり考慮しておらず、Webサーバも Apache のためモジュール版でも良いと判断。</p> <p>動作を切り替えます。</p> <pre><code class="bash"># less /etc/httpd/conf/httpd.conf ## 略 Include conf.modules.d/*.conf </code></pre> <p>念のためモジュール読み込みの記述があることを確認。</p> <pre><code class="bash"># ls /etc/httpd/conf.modules.d/ 00-base.conf 00-lua.conf 00-optional.conf 00-ssl.conf 01-cgi.conf 10-proxy_h2.conf README 00-dav.conf 00-mpm.conf 00-proxy.conf 00-systemd.conf 10-h2.conf 15-php.conf </code></pre> <p>関係しそうなのは <code>00-mpm.conf</code>, <code>01-cgi.conf</code>, <code>15-php.conf</code> 辺りでしょうか。</p> <pre><code class="bash"># less /etc/httpd/conf.modules.d/15-php.conf # Cannot load both php5 and php7 modules <IfModule !mod_php5.c> <IfModule prefork.c> LoadModule php7_module modules/libphp7.so </IfModule> </IfModule> </code></pre> <p>ここはそのまま。</p> <pre><code class="bash"># less /etc/httpd/conf.modules.d/01-cgi.conf # This configuration file loads a CGI module appropriate to the MPM # which has been configured in 00-mpm.conf. mod_cgid should be used # with a threaded MPM; mod_cgi with the prefork MPM. <IfModule mpm_worker_module> LoadModule cgid_module modules/mod_cgid.so </IfModule> <IfModule mpm_event_module> LoadModule cgid_module modules/mod_cgid.so </IfModule> <IfModule mpm_prefork_module> LoadModule cgi_module modules/mod_cgi.so </IfModule> </code></pre> <p>ここもそのまま。</p> <pre><code class="bash"># less /etc/httpd/conf.modules.d/00-mpm.conf # Select the MPM module which should be used by uncommenting exactly # one of the following LoadModule lines. See the httpd.conf(5) man # page for more information on changing the MPM. # prefork MPM: Implements a non-threaded, pre-forking web server # See: http://httpd.apache.org/docs/2.4/mod/prefork.html # # NOTE: If enabling prefork, the httpd_graceful_shutdown SELinux # boolean should be enabled, to allow graceful stop/shutdown. # #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so # worker MPM: Multi-Processing Module implementing a hybrid # multi-threaded multi-process web server # See: http://httpd.apache.org/docs/2.4/mod/worker.html # #LoadModule mpm_worker_module modules/mod_mpm_worker.so # event MPM: A variant of the worker MPM with the goal of consuming # threads only for connections with active processing # See: http://httpd.apache.org/docs/2.4/mod/event.html # LoadModule mpm_event_module modules/mod_mpm_event.so </code></pre> <p>変更するのはここ。</p> <pre><code>- #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so + LoadModule mpm_prefork_module modules/mod_mpm_prefork.so - LoadModule mpm_event_module modules/mod_mpm_event.so # LoadModule mpm_event_module modules/mod_mpm_event.so </code></pre> <p>上述のうち2ヶ所を反転させます。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.out48.com/archives/5636/">CentOSにApacheとPHP入れてPHPファイルを表示しようとしたら503エラー Output48</a></li> </ul> <p>これでOK。起動も確認できました。</p> <p>テンプレートとして上述を反転させた <code>00-mpm.conf</code> を用意し、エントリポイントでファイルコピーして設定を上書きすることで対処しました。</p> <p><a href="https://crieit.now.sh/upload_images/abe7eb81a2b7f6580feb784cb81cdf1361cb21ea49eef.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/abe7eb81a2b7f6580feb784cb81cdf1361cb21ea49eef.jpg?mw=700" alt="最終的に AlmaLinux の Docker Compose で起動、確認した phpinfo() の画面" /></a></p> <p>最終的に AlmaLinux の Docker Compose を作成して起動し、ブラウザで該当の PHPファイル にアクセスし、 <code>phpinfo()</code> の画面が表示されることを確認できました。OK。</p> <h3 id="SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty"><a href="#SSLCertificateFile%3A+file+%27%2Fetc%2Fpki%2Ftls%2Fcerts%2Flocalhost.crt%27+does+not+exist+or+is+empty">SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty</a></h3> <p>上述のエラーの他に</p> <blockquote> <p>SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty</p> </blockquote> <p>localhost のSSL証明書がない、というエラーにも遭遇しました。</p> <p>なければ作れば良いだけ、上述で</p> <pre><code class="bash">echo ServerName www.example.com:80 >> /etc/httpd/conf/httpd.conf </code></pre> <p>としているので、このダミードメインを使います。</p> <pre><code class="bash"># openssl req -new -newkey rsa:2048 -nodes -out /etc/pki/tls/certs/localhost.csr -keyout /etc/pki/tls/private/localhost.key -subj &quot;/C=/ST=/L=/O=/OU=/CN=www.example.com&quot; ## 略 # openssl x509 -days 365 -req -signkey /etc/pki/tls/private/localhost.key -in /etc/pki/tls/certs/localhost.csr -out /etc/pki/tls/certs/localhost.crt Signature ok subject=CN = www.example.com Getting Private key </code></pre> <p>これでOK。 <code>ssl.conf</code> には記述はあるのですが……。</p> <h3 id="MySQL"><a href="#MySQL">MySQL</a></h3> <p>次に MySQL 側を。こちらはほぼ手を加える必要はないという想定です。</p> <pre><code class="bash"># dnf localinstall https://dev.mysql.com/get/mysql80-community-release-el8-2.noarch.rpm ## 略 Package mysql80-community-release-el8-2.noarch is already installed. Dependencies resolved. Nothing to do. Complete! </code></pre> <p>CentOS8 用ということでリポジトリの入れ方を少し変更。</p> <pre><code class="bash"># ls /etc/yum.repo.d/ CentOS-Linux-AppStream.repo CentOS-Linux-Media.repo epel-testing.repo CentOS-Linux-BaseOS.repo CentOS-Linux-Plus.repo mysql-community.repo CentOS-Linux-ContinuousRelease.repo CentOS-Linux-PowerTools.repo mysql-community-source.repo CentOS-Linux-Debuginfo.repo CentOS-Linux-Sources.repo remi-modular.repo CentOS-Linux-Devel.repo epel-modular.repo remi.repo CentOS-Linux-Extras.repo epel-playground.repo remi-safe.repo CentOS-Linux-FastTrack.repo epel.repo CentOS-Linux-HighAvailability.repo epel-testing-modular.repo </code></pre> <p><code>mysql-community.repo</code>, <code>mysql-community-source.repo</code> の2つが追加されたことを確認。</p> <pre><code class="bash"># dnf module disable mysql ## 略 Complete! </code></pre> <p>デフォルトの MySQL がいると邪魔になるので無効化して</p> <pre><code class="bash"># dnf -y install mysql-community-devel mysql-community-server ## 略 Installed: mysql-community-client-8.0.27-1.el8.x86_64 mysql-community-client-plugins-8.0.27-1.el8.x86_64 mysql-community-common-8.0.27-1.el8.x86_64 mysql-community-devel-8.0.27-1.el8.x86_64 mysql-community-libs-8.0.27-1.el8.x86_64 mysql-community-server-8.0.27-1.el8.x86_64 net-tools-2.0-0.52.20160912git.el8.x86_64 Complete! </code></pre> <p>インストール完了。</p> <pre><code class="bash"># mysqld --version /usr/sbin/mysqld Ver 8.0.27 for Linux on x86_64 (MySQL Community Server - GPL) </code></pre> <p>デフォルトでは <code>8.0.26</code> だったバージョンが地味に <code>8.0.27</code> に上がりました。</p> <pre><code class="bash"># grep 'temporary password' /var/log/mysqld.log yyyy-mm-ddThh:ii:ss.zzzzzzZ 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: XXXXXXXXXXXX </code></pre> <p>初期パスワードの出現位置が半角スペース区切りで13番目であることを確認。これはエントリポイントで <code>awk</code> を使って抽出、初期パスワードを環境変数の値で書き換える処理で使用するため個人的には重要ポイント。ここは変更しなくて良さそうです。</p> <pre><code class="bash"># cat /etc/my.cnf [mysqld] ## 略 datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid </code></pre> <p>デフォルトで4つパラメータが指定されています。うち3つはテンプレートの設定ファイルに記述がされているので不要、 <code>pid-file</code> だけ現時点では指定がないため、これだけ <code>base.cnf</code> に移植します。</p> <p><code>/etc/my.cnf</code> には上述4つを削除した代わりに <code>!includedir /etc/my.cnf.d</code> を末尾に追加したものを現行の <code>my.cnf</code> と差し替え。</p> <p>これで MySQL 側は良さそうです。</p> <p>なお、 phpMyAdmin は公式イメージをそのまま使っているので変更なし。</p> <p>以上で一通り動作検証できたので、これをベースに AlmaLinux 用に書き換えれば良さそうです。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="Docker"><a href="#Docker">Docker</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://hub.docker.com/_/almalinux?tab=tags">almalinux Tags | Docker Hub</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://hub.docker.com/_/centos?tab=tags">centos Tags | Docker Hub</a></li> </ul> <h3 id="AlmaLinux"><a href="#AlmaLinux">AlmaLinux</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://blog.apar.jp/linux/15554/">AlmaLinux 8.4 LAMPサーバインストールメモ【Apache2.4+MySQL8.0+PHP7.4】 | あぱーブログ</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yamada-hakase/items/17b41d33e30232b69fe2">AlmaLinuxを使ってみた(後編) - Qiita</a></li> </ul> <h3 id="dnf"><a href="#dnf">dnf</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://blog.trippyboy.com/2021/terraform/almalinux%E3%81%ABterraform%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92yum%E3%81%A7%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B%E3%81%AE%E5%B7%BB/">Almalinuxにterraformコマンドをyumで導入するの巻 - TrippyBoyの愉快な日々</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/40937056/dnf-missing-config-manager-command">linux - DNF missing config-manager command - Stack Overflow</a></li> </ul> <h3 id="remi"><a href="#remi">remi</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="http://rpms.remirepo.net/">Remi's RPM repository</a></li> </ul> <h3 id="AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message"><a href="#AH00558%3A+httpd%3A+Could+not+reliably+determine+the+server%27s+fully+qualified+domain+name%2C+using+192.0.2.1.+Set+the+%27ServerName%27+directive+globally+to+suppress+this+message">AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.0.2.1. Set the 'ServerName' directive globally to suppress this message</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/sachiko-kame/items/a6deebbad207d627b598">[Docker]AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using ***.***.*.*. Set the 'ServerName' directive globally to suppress this message - Qiita</a></li> </ul> <h3 id="PHP"><a href="#PHP">PHP</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://mebee.info/2020/03/12/post-7365/">CentOs8 php7.4をインストールする | mebee</a></li> </ul> <h3 id="(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed"><a href="#%282%29No+such+file+or+directory%3A+AH02454%3A+FCGI%3A+attempt+to+connect+to+Unix+domain+socket+%2Frun%2Fphp-fpm%2Fwww.sock+%28%2A%29+failed">(2)No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /run/php-fpm/www.sock (*) failed</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/58365479/no-such-file-or-directory-ah02454-fcgi-attempt-to-connect-to-unix-domain-sock">apache - No such file or directory: AH02454: FCGI: attempt to connect to Unix domain socket /var/run/php/php5.6-fpm.sock (*) failed - Stack Overflow</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.out48.com/archives/5636/">CentOSにApacheとPHP入れてPHPファイルを表示しようとしたら503エラー Output48</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://ja.stackoverflow.com/questions/46727/amazon-linux2%E3%81%A7%E3%82%A8%E3%83%A9%E3%83%BCah02454%E3%82%84ah01079%E3%81%AA%E3%81%A9%E3%81%8C%E5%87%BA%E3%81%A6httpd%E3%81%8C%E3%81%86%E3%81%BE%E3%81%8F%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%BE%E3%81%9B%E3%82%93">php - amazon-linux2でエラーAH02454やAH01079などが出てhttpdがうまく起動しません - スタック・オーバーフロー</a></li> </ul> <h3 id="php-fpm"><a href="#php-fpm">php-fpm</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc">nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する - Qiita</a></li> </ul> <h3 id="SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty"><a href="#SSLCertificateFile%3A+file+%27%2Fetc%2Fpki%2Ftls%2Fcerts%2Flocalhost.crt%27+does+not+exist+or+is+empty">SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://daredemose.com/linux/ssl/">SSL/TLS | 初心者向けプログラミング講座</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://hacknote.jp/archives/51779/">いつの間にか作られてる /etc/pki/tls/certs/localhost.crt と /etc/pki/tls/private/localhost.key の謎 | ハックノート</a></li> </ul> <h3 id="MySQL"><a href="#MySQL">MySQL</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yasushi-jp/items/1579c301075d693a2a36">MySQL 8.0 を CentOS 8.1 にインストールする手順 - Qiita</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17871 2021-12-17T23:53:02+09:00 2021-12-17T23:53:02+09:00 https://crieit.net/posts/no-effect-cd-command-in-dockerfile-20211217 Dockerfile で cd が効かない <p>Dockerfile で cd コマンドが効かなかったので対処。</p> <h2 id="現象"><a href="#%E7%8F%BE%E8%B1%A1">現象</a></h2> <pre><code class="dockerfile">RUN cd /var/hoge/ RUN wget https://example.jp/hoge_package.tar.gz RUN tar zxvf hoge_package.tar.gz RUN cd hoge_package </code></pre> <p>という風に記述したところ、「<code>hoge_package</code> はありません」という旨のエラーで怒られました。</p> <h2 id="原因"><a href="#%E5%8E%9F%E5%9B%A0">原因</a></h2> <p>Dockerfile ではコマンドごとにコンテナを作るため、カレントディレクトリは常にルートになるとのことです。</p> <h2 id="対処"><a href="#%E5%AF%BE%E5%87%A6">対処</a></h2> <p>cd の後に <code>\</code> でコマンドを繋げるという方法もありますが、今回は <code>WORKDIR</code> で対処。</p> <pre><code class="dockerfile">WORKDIR /var/hoge/ RUN wget https://example.jp/hoge_package.tar.gz RUN tar zxvf hoge_package.tar.gz WORKDIR hoge_package </code></pre> <p>これでOKです。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://christina04.hatenablog.com/entry/2014/10/31/101510">Dockerfile で cd が効かない - Carpe Diem</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/DogFortune/items/05bf806ecbb256a823f8">Dockerfileの「RUN mkdir /path && cd /path」はWORKDIRで一発 - Qiita</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17849 2021-12-13T23:56:29+09:00 2021-12-13T23:56:29+09:00 https://crieit.net/posts/awk-only-match-last-line-for-mysql-init-password-20211213 awk で条件に合致する最後の行のみ処理する <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>次のようなシチュエーションを考えます。</p> <ul> <li>Docker 環境で MySQL の初期パスワードを変更するシェルスクリプトをエントリポイントで実行</li> <li>MySQL のログ (特に <code>mysql-error.log</code>) をボリュームマウントしてファイルの永続化を実施している</li> <li>このプロジェクトでディレクトリを使い回して1回目の MySQL のログを削除せずに2回目のビルドを実行する</li> </ul> <p>このとき、 <code>mysql-error.log</code> 内に初期パスワードが2回記録されることになります。</p> <p>すると、条件に合致する最初の行(1回目の初期パスワード)を処理しようとした際に(2回目のパスワードが設定されているため)パスワードが合致せず、処理が失敗してしまう遭遇したので対処しました。</p> <h2 id="対処"><a href="#%E5%AF%BE%E5%87%A6">対処</a></h2> <pre><code>- DB_INIT_PASSWORD=$(sudo grep 'temporary password' /var/log/mysql/mysql-error.log | sudo awk '{print $13}') + DB_INIT_PASSWORD=$(sudo grep 'temporary password' /var/log/mysql/mysql-error.log | sudo awk 'END{print $13}') </code></pre> <p>エントリポイントのシェルスクリプトで、 <code>awk</code> に <code>END</code> を付け加えました。処置としてはこれだけ。</p> <h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2> <p>試しに、中身のシェルスクリプトを該当環境で手動で実行してみます。</p> <h3 id="変更前"><a href="#%E5%A4%89%E6%9B%B4%E5%89%8D">変更前</a></h3> <pre><code class="bash"># sudo grep 'temporary password' /var/log/mysql/mysql-error.log | sudo awk '{print $13}' XXXXXXXXXXXX YYYYYYYYYYYY </code></pre> <p>変更前では複数マッチしていることが確認できます。このうち、最初のパスワード <code>XXXXXXXXXXXX</code> で認証をくぐって理しようとすると冒頭のようにパスワードが合致せず失敗します。</p> <h3 id="変更後"><a href="#%E5%A4%89%E6%9B%B4%E5%BE%8C">変更後</a></h3> <pre><code class="bash"># sudo grep 'temporary password' /var/log/mysql/mysql-error.log | sudo awk 'END{print $13}' YYYYYYYYYYYY </code></pre> <p>そこで変更後。今度は1回目のパスワード <code>XXXXXXXXXXXX</code> がヒットせず、2回目のパスワード <code>YYYYYYYYYYYY</code> のみがヒットするようになりました。</p> <p>これで Docker Compose 全体のビルドもコケなくなりました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://orebibou.com/ja/home/201607/20160725_001/">awkで最後の行(最終行)のみ処理を行わせる | 俺的備忘録 -なんかいろいろ-</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17843 2021-12-10T23:34:08+09:00 2021-12-10T23:34:08+09:00 https://crieit.net/posts/ssh-login-by-password-in-docker-container-20211210 Dockerコンテナ に SSHログイン できるようにする(パスワード方式) <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>Dockerコンテナ でファイル永続化をすると便利ではあるのですが、 Windows-Linux間 だと異なるファイルシステム間で整合性を保つ処理でもたつき、大量のファイルがある場合は体感的には加速度的に遅延がひどくなってしまいます。</p> <p>一時的な試験であれば、ファイル永続化を捨てるという選択肢を取ることができると思います。</p> <p>そこで課題となるのは、ファイルをどうやってコンテナの中に持ち込むか。</p> <p>そのための一つの方法として、 SFTP を採ることにしました。通常のサーバと同様に、 SFTP で接続してファイルをアップロードする、と。</p> <p>であれば、 SSHログイン できなければ話が成立しないので、 SSHログイン できるようにしてみたいと思います。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <ul> <li>ベース: <a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/docker_compose_ambergrease">arm-band/docker_compose_ambergrease</a></li> </ul> <p>例によって Ambergrease をベースに使います。</p> <h3 id=".env"><a href="#.env">.env</a></h3> <pre><code class="env"># 略 WEB_HOST_PORTSSH=2222 WEB_CONTAINER_PORTSSH=22 WEB_SSH_USER=root WEB_SSH_PASSWORD=Password-1234 # 略 </code></pre> <p>今回はWebサーバのコンテナに SSHログイン したいので、必要なパラメータを追加します。</p> <p>管理者権限ユーザもハードコーディングはしたくないので一緒に変数にしておきます。ただ、 Docker で一時的な試験環境なので SSH はパスワード認証方式で良いかな、と。</p> <h3 id="docker-compose.yml"><a href="#docker-compose.yml">docker-compose.yml</a></h3> <pre><code class="yml"> web: build: context: ./apache/docker dockerfile: Dockerfile args: # 略 WEB_HOST_PORTSSH: $WEB_HOST_PORTSSH WEB_CONTAINER_PORTSSH: $WEB_CONTAINER_PORTSSH WEB_SSH_USER: $WEB_SSH_USER WEB_SSH_PASSWORD: $WEB_SSH_PASSWORD # 略 volumes: # 略 # apache virtual host # - ./apache/www:/var/www/$WEB_ROOT_DIRECTORY/web # 略 ports: # 略 - "$WEB_HOST_PORTSSH:$WEB_CONTAINER_PORTSSH" entrypoint: bash -c "bash /workspace/entrypoint_web.sh $WEB_ROOT_DIRECTORY $WEB_DOMAIN $WEB_HOST_PORTNUM $WEB_CONTAINER_PORTNUM $WEB_HOST_PORTSSL $WEB_CONTAINER_PORTSSL $WP_CLI $WEB_SSH_USER $WEB_SSH_PASSWORD && /bin/bash" # 略 </code></pre> <p>主に変更した部分のみ掲載。</p> <ul> <li><code>args</code>: <code>.env</code> で追加したホスト・コンテナ双方のポート番号を引数に追加</li> <li><code>volumes</code>: 今回の本題。ファイル数が多いと激重になってしまうので仮想ホストのファイル永続化を切っています</li> <li><code>ports</code>: <code>.env</code> で追加したホスト・コンテナ双方のポート番号を紐付け</li> <li><code>entrypoint</code>: エントリポイントとして実行するシェルスクリプトに渡す引数に <code>.env</code> で追加した <code>$WEB_SSH_USER</code>, <code>$WEB_SSH_PASSWORD</code> (SSHログインユーザ名・パスワード)を追加</li> </ul> <h3 id="Dockerfile"><a href="#Dockerfile">Dockerfile</a></h3> <pre><code class="dockerfile"># 略 # yum install RUN yum -y update && yum -y install \ # 略 # network ss (instaed of netstat) iproute \ # SSH openssh-server # 略 # SSH RUN mkdir /var/run/sshd </code></pre> <p>追加した項目は <code>openssh-server</code> のインストールと、ディレクトリ <code>/var/run/sshd</code> の作成のみ。それ以外の処理はエントリポイント側に投げました。</p> <h3 id="entrypoint_web.sh"><a href="#entrypoint_web.sh">entrypoint_web.sh</a></h3> <pre><code class="sh"># 略 # SSH sed -ri 's/^#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config echo "${8}:${9}" | chpasswd ssh-keygen -t rsa -N "" -f /etc/ssh/ssh_host_rsa_key /usr/sbin/sshd -D & </code></pre> <p>先程述べた通り、 SSHサーバ についての主な処理はこちらに追加しました。</p> <ol> <li>管理者権限のログインを有効化し</li> <li>パスワードを上述の Docker Compose から引数で渡された <code>.env</code> の値に書き換え</li> <li>使用しないものの存在しないとエラーになるので秘密鍵を生成</li> <li>最後にフォアグラウンドで SSHサーバ を起動</li> </ol> <p><a href="https://crieit.now.sh/upload_images/cd8f856540941fe0320d9bb4443a1b6561b0d2f9345c0.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/cd8f856540941fe0320d9bb4443a1b6561b0d2f9345c0.jpg?mw=700" alt="TeraTerm で SSH ログイン" /></a></p> <p><a href="https://crieit.now.sh/upload_images/9cd07317d7e8c28ade7e61b9c5fa91ed61b0d308ce42f.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9cd07317d7e8c28ade7e61b9c5fa91ed61b0d308ce42f.jpg?mw=700" alt="TeraTerm で SSH ログイン" /></a></p> <p><a href="https://crieit.now.sh/upload_images/fe8fed10666c348a7e780afb22263ab161b0d324ef9d5.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/fe8fed10666c348a7e780afb22263ab161b0d324ef9d5.jpg?mw=700" alt="TeraTerm で SSH ログイン" /></a></p> <p>これで SSHサーバ が起動し、 <code>.env</code> でアクセスできるようになりました。</p> <p>なお、ポート番号は <code>.env</code> のホスト用のポートなので接続する際は注意。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://nxmnpg.lemoda.net/ja/8/sshd">sshd(8) manページ</a>: <code>-D</code> について</li> <li><a target="_blank" rel="nofollow noopener" href="https://pocketcode.net/docker-centos7-ssh-connect">Dockerで構築したCentOS7にSSH接続する | ポケットコード</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://genchan.net/it/virtualization/docker/8547/">【Docker】CentOS7,8をコンテナ上で動作とSSHアクセスまで | インフラエンジニアの技術LOG</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17841 2021-12-09T00:28:54+09:00 2021-12-09T00:28:54+09:00 https://crieit.net/posts/memory-limit-up-of-phpmyadmin-docker-compose-20211209 Docker の phpMyAdmin公式イメージ でメモリ上限等を増やす (Docker Compose 使用) <p>表題の通り、 phpMyAdmin公式イメージ でメモリ上限等を増やす方法をメモ。</p> <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>phpMyAdmion で大量のデータをインポートしようとしたら、以下のエラーが出て失敗してしまいました。</p> <blockquote> <p>Fatal error: Allowed memory size of XXXXXXXXX bytes exhausted (tried to allocate 16 bytes) in ......</p> </blockquote> <p>メモリ不足ですね……そのため、 phpMyAdmin の設定を変更します。</p> <h2 id="対処"><a href="#%E5%AF%BE%E5%87%A6">対処</a></h2> <h3 id="docker-compose.yml"><a href="#docker-compose.yml">docker-compose.yml</a></h3> <pre><code class="yml"> phpmyadmin: image: phpmyadmin/phpmyadmin volumes: # sessions - ./phpmyadmin/sessions:/sessions - ./phpmyadmin/conf/phpmyadmin-misc.ini:/usr/local/etc/php/conf.d/phpmyadmin-misc.ini </code></pre> <p><code>docker-compose.yml</code> でこのようにします。</p> <p>ディレクトリ・ファイルは次の2つをボリュームマウントして永続化しています。</p> <ul> <li><code>/phpmyadmin/sessions</code></li> <li><code>/phpmyadmin/conf/phpmyadmin-misc.ini</code></li> </ul> <h3 id="/phpmyadmin/conf/phpmyadmin-misc.ini"><a href="#%2Fphpmyadmin%2Fconf%2Fphpmyadmin-misc.ini">/phpmyadmin/conf/phpmyadmin-misc.ini</a></h3> <pre><code class="ini">allow_url_fopen = Off max_execution_time = 600 memory_limit = 64M post_max_size = 64M upload_max_filesize = 64M </code></pre> <p>後は <code>phpmyadmin-misc.ini</code> でパラメータを記述してあげればOK。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://deep-blog.jp/engineer/1887/">PHPのメモリー不足(Allowed memory size) | エンジニア足立のコーディング日記</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.yuulinux.tokyo/16613/">docker-compose phpmyadmin アップロード制限緩和設定 | 優技録</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17814 2021-12-04T00:20:20+09:00 2021-12-04T00:20:20+09:00 https://crieit.net/posts/sed-0 置換ができない/複数ある場合に sed の終了コード0以外にする <p>本記事は、 <a target="_blank" rel="nofollow noopener" href="https://qiita.com/advent-calendar/2021/shellscript">シェルスクリプト Advent Calendar 2021</a> の 4日目 の記事だ。<br /> そして、 <strong>且つ</strong> <a target="_blank" rel="nofollow noopener" href="https://qiita.com/advent-calendar/2021/docker">docker Advent Calendar 2021</a> 4日目 の記事でもある。</p> <p>どちらのカレンダーもまだまだスッカスカなので、禁じ手で埋めにかかってしまった。</p> <hr /> <p><a target="_blank" rel="nofollow noopener" href="https://matsuand.github.io/docs.docker.jp.onthefly/docker-hub/official_images/">Docker 公式イメージ</a> などをベースにして、カスタムしてイメージをビルドして使おうとした際、 なるべくなら <code>/etc/apt/apt.conf.d/</code> 等のように、設定用の<strong>ファイルを追加</strong>して、ツール側がいい感じにマージして利用してくれるのが望ましい。<br /> しかし、 場合によってはやむを得ず、既存のファイルを <code>sed</code> コマンドなどで編集せざるを得ないこともあるだろう。</p> <p>カスタムイメージの Dockerfile をビルドする際に、当初は意図通り書き換えられていても、イメージが更新された結果、イメージのリビルド時にファイルの書き換えが意図しない結果となってしまう場合がある。 <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p> <p>通常、 <code>sed</code> コマンドは、置換が発生してもしなくても、 終了コード 0 で終了する。<br /> このため、書き換えの成否にかかわらず、 docker build 時にエラーにならないため、コンテナ実行時に初めて置換が意図しない結果だったことに気づくことがある。</p> <p>そこで、<strong><code>sed</code> コマンドの書き換えで適切なパターンが見つからなかった</strong>場合に 0以外の終了コードを返し、<strong>ビルド時にエラー</strong>とする方法を考える。</p> <p>以下、 <code>sed</code> は GNU sed を前提とし、 "行頭の foo" を BARfooBAR に置き換える場合の例。</p> <h2 id="ひとつもヒットしなかったら終了コード16 のエラー"><a href="#%E3%81%B2%E3%81%A8%E3%81%A4%E3%82%82%E3%83%92%E3%83%83%E3%83%88%E3%81%97%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E3%82%89%E7%B5%82%E4%BA%86%E3%82%B3%E3%83%BC%E3%83%8916+%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC">ひとつもヒットしなかったら終了コード16 のエラー</a></h2> <p>まずは、 書き換えるパターンが見つからなかった場合に、エラーコードを返す方法。</p> <pre><code class="bash">sed -e '/^foo/{s//BAR\0BAR/;h};$!b;p;x;/./Q;Q16' </code></pre> <p>参考: https://stackoverflow.com/a/15966279</p> <p>ざっとコマンドの流れを解説すると、以下のようになる。</p> <ol> <li>まず、 <a target="_blank" rel="nofollow noopener" href="https://kuma35.github.io/sed47doc-jp/sed.html#Regexp-Addresses">正規表現アドレス</a> で置換する行を選択する。</li> <li>ブロック <code>{}</code> を用いて、正規表現に一致する行について以下を実行する。 <ol> <li><a target="_blank" rel="nofollow noopener" href="https://kuma35.github.io/sed47doc-jp/sed.html#The-_0022s_0022-Command">s コマンド</a> で、<a target="_blank" rel="nofollow noopener" href="https://kuma35.github.io/sed47doc-jp/sed.html#regexp-extensions">後方参照</a>を使って FOObarBAR に置換する。<br /> <a target="_blank" rel="nofollow noopener" href="https://kuma35.github.io/sed47doc-jp/sed.html#Regexp-Addresses">空の正規表現 '//'は最後の正規表現のマッチを繰り返</a>すので、正規表現アドレスでマッチした "行頭の foo" が置き換えられる。</li> <li><a target="_blank" rel="nofollow noopener" href="https://kuma35.github.io/sed47doc-jp/sed.html#sed-commands-list">h コマンド</a> で、パターンスペース の内容をホールドスペース (sed 内のクリップボードみたいなもの) にコピーする。</li> </ol></li> <li><code>$!b</code> の部分は、最終行でなければ次のサイクルに移動する。 すなわち、以降のコマンドは<strong>最終行でのみ実行</strong>される。</li> <li><a target="_blank" rel="nofollow noopener" href="https://kuma35.github.io/sed47doc-jp/sed.html#The-_0022s_0022-Command">p コマンド</a> でパターンスペースの内容を出力にプリントする。</li> <li><a target="_blank" rel="nofollow noopener" href="https://kuma35.github.io/sed47doc-jp/sed.html#sed-commands-list">x コマンド</a> でパターンスペースの内容とホールドスペースをスワップする。<br /> <strong>パターンスペースの内容は結果的に</strong> 、1度でも最初の正規表現がヒットすればその文字列に、 最後まで一度も正規表現がヒットしなければ空っぽになる。</li> <li>最後、パターンスペースの内容が空でない (即ち、1度以上正規表現がヒットした) なら、 終了コード 0 で終了し、 そうでなければ 16 で終了する。</li> </ol> <h2 id="ヒットしなければ終了コード16, 2つ以上ヒットしたら終了コード32 のエラー"><a href="#%E3%83%92%E3%83%83%E3%83%88%E3%81%97%E3%81%AA%E3%81%91%E3%82%8C%E3%81%B0%E7%B5%82%E4%BA%86%E3%82%B3%E3%83%BC%E3%83%8916%2C+2%E3%81%A4%E4%BB%A5%E4%B8%8A%E3%83%92%E3%83%83%E3%83%88%E3%81%97%E3%81%9F%E3%82%89%E7%B5%82%E4%BA%86%E3%82%B3%E3%83%BC%E3%83%8932+%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC">ヒットしなければ終了コード16, 2つ以上ヒットしたら終了コード32 のエラー</a></h2> <p>さらに一歩踏み込んで、 書き換えるパターンが見つからない場合と、 2つ以上見つかってしまった場合<strong>両方</strong>で、エラーにする方法。</p> <pre><code class="bash">sed -e '/^foo/{s//BAR\0BAR/;x;/./Q32;g};$!b;p;x;/./Q;Q16' </code></pre> <p>基本的な動きは、ひとつもヒットしなかったパターンと同じだ。<br /> ただ、ブロック <code>{}</code> 内部のコマンドを以下のように変更して、複数ヒットした場合にエラーで終了している。</p> <ol> <li>まず、 正規表現アドレス で置換する行を選択する。</li> <li>ブロック <code>{}</code> を用いて、正規表現に一致する行について以下を実行する。 <ol> <li>s コマンド で、後方参照を使って FOObarBAR に置換する。</li> <li><a target="_blank" rel="nofollow noopener" href="https://kuma35.github.io/sed47doc-jp/sed.html#sed-commands-list">x コマンド</a> でパターンスペースの内容とホールドスペースをスワップする。<br /> <strong>パターンスペースの内容は結果的に</strong> 、以前の行でも正規表現がヒットすればその文字列に、 最後まで一度も正規表現がヒットしなければ空っぽになる。</li> <li>パターンスペースの内容が空でない (即ち、正規表現のヒットが2回目) なら、 終了コード 32 で<strong>エラー終了</strong>し、 そうでなければそのまま次へ。</li> <li><a target="_blank" rel="nofollow noopener" href="https://kuma35.github.io/sed47doc-jp/sed.html#sed-commands-list">g コマンド</a> でホールドスペースの内容をパターンスペースにコピーして戻す</li> </ol></li> <li>以降は「ひとつもヒットしなかったら…」と同じ</li> </ol> <p>なお、このコマンドは、 2つヒットした時点で出力が止まる。</p> <h2 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h2> <p>モダンなプログラミング言語が軒並み型推論でコンパイル時にエラーとするように、 Dockerfile もビルド時にエラーにしてしまおう。</p> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>カスタムイメージの Dockerfile ベースイメージを選択する際、基本的にはタグである程度絞っておくべきだが、それはさておき。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> advanceboy tag:crieit.net,2005:PublicArticle/17809 2021-12-03T00:01:29+09:00 2021-12-03T02:33:10+09:00 https://crieit.net/posts/Samba-Docker-Desktop Samba が動く Docker Desktop のコンテナで、ボリューム内のファイルを見る <p>本記事は、 <a target="_blank" rel="nofollow noopener" href="https://qiita.com/advent-calendar/2021/docker">docker Advent Calendar 2021</a> 2日目 の記事だ。<br /> 昨日は、 <a target="_blank" rel="nofollow noopener" href="https://qiita.com/subretu">@subretu</a>氏 の <a target="_blank" rel="nofollow noopener" href="https://qiita.com/subretu/items/31a387510f84daaa4c1c">DockerfileにおけるCMDとRUNの挙動</a> だった。</p> <hr /> <p>docker のコンテナやボリュームの中身を見る際に、 ホスト PC から SMB ファイル共有で参照できると都合が良い。</p> <p>と言うことで以前、以下のような記事を作成したが、 Docker Desktop では利用できない問題があった。</p> <p><a target="_blank" rel="nofollow noopener" href="https://aquasoftware.net/blog/?p=1259">無認証 SMB を samba で秒で立ち上げる Dockerfile (& docker-compose) | Aqua Ware つぶやきブログ</a></p> <p>今回は、それを解消する手段について紹介したい。</p> <p>先に断っておくが、私自身でいくつかの PC で試したところ、上手くいく PC とダメな PC がハッキリと分かれてしまい、現時点ではどのような条件だとダメなのかハッキリわかっていない。</p> <h2 id="何故 Docker Desktop では Samba にアクセスできないのか"><a href="#%E4%BD%95%E6%95%85+Docker+Desktop+%E3%81%A7%E3%81%AF+Samba+%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B">何故 Docker Desktop では Samba にアクセスできないのか</a></h2> <p>Windows の SMB over TCP/IP アクセス機能は、接続先が 445 番ポートでないと利用できない制限がある。</p> <p>ところが、 Docker Desktop で 445 番ポートをリッスンしようとしても、 ホスト OS 側の <code>LanmanServer</code> サービス ("Server" と言う表示名のもの) が常に localhost の 445 番ポートを占有しているため、ポートをリッスンできずに失敗してしまう。</p> <p>さらに、この <code>LanmanServer</code> サービスは、 Docker Desktop サービスがこれに依存しているため、 このサービスを止めることもできない。</p> <p>このため、なんとか localhost の 445 番ポート以外をリッスンさせてる方法を考えなくてはならない。</p> <h2 id="ループバックアダプターと portproxy を使う"><a href="#%E3%83%AB%E3%83%BC%E3%83%97%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%83%BC%E3%81%A8+portproxy+%E3%82%92%E4%BD%BF%E3%81%86">ループバックアダプターと portproxy を使う</a></h2> <p>結論から言うと、 <a target="_blank" rel="nofollow noopener" href="https://docs.microsoft.com/ja-jp/troubleshoot/windows-server/networking/install-microsoft-loopback-adapter"><strong>"ループバックアダプター"</strong></a> と <strong>"portproxy"</strong> という Windows 組み込みの機能を利用する。</p> <p>ループバックアダプターとは、一言で言うと <strong>仮想的なネットワークアダプタ (NIC)</strong> だ。<br /> この 仮想NIC に <strong>適当なIPアドレス</strong> を割り当てて、 その 445 番ポートにアクセスすると、 localhost の <strong>445 番以外</strong> のアドレスに <strong>portproxy させる</strong> ことができる。<br /> Docker Desktop 側で その <strong>445 番以外</strong> のアドレスをリッスンしておけば、問題を回避できるはずだ。</p> <p><img src="http://www.plantuml.com/plantuml/svg/RP5FImCn4CNl-HIFdFJGmgwjrAL8_NDK48fuwMMQJRKqoIn9LXJfVdR3_baMyPZtVk_D3Dc4I3xMrWYlLIJtRZJaouF4Zm18HVQGhq5x2GgeWq_gmPDDq2Eha_PWXxVjKyS39KNQKz3uP5DRtMgEouHld--Xs4KwkhvDPNq8EBge_O5Kueh5OjdP2JuUMk0ywGbizSxzQSfRe9k9zMpsdv8LmzDoxQBeQYUJ3Iio7nnYSRKQbaZFRea9Ts6Ogpsf4wYaAicNEvVTvFFiUZNFbujvFfumW0BzDLWtJTzPe68VOQbARXqycjkHBt2db0v1O9IIFGObq8Ohpr_V0AGuYursPVh5Nm00" alt="" /></p> <h3 id="ループバックアダプターのインストール"><a href="#%E3%83%AB%E3%83%BC%E3%83%97%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%83%BC%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">ループバックアダプターのインストール</a></h3> <ol> <li>Win+R で「ファイルを指定して実行」を開き、 <code>hdwwiz.exe</code> を実行する<br /> <a href="https://crieit.now.sh/upload_images/89ac916ec4d187f3ec435778892a65c961a8e0144aefb.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/89ac916ec4d187f3ec435778892a65c961a8e0144aefb.png?mw=700" alt="smb-on-docker-desktop-01-01.png" /></a></li> <li>ハードウェア追加ウィザードで、「一覧から選択したハードウェアをインストールする」を選択する<br /> <a href="https://crieit.now.sh/upload_images/f39fdbeb6ba5eaf4cba419fa4f8fec2461a8e01e346af.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/f39fdbeb6ba5eaf4cba419fa4f8fec2461a8e01e346af.png?mw=700" alt="smb-on-docker-desktop-01-02.png" /></a> <a href="https://crieit.now.sh/upload_images/efd3fb5883aa94c2dc8825dd4d52625f61a8e021bb45f.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/efd3fb5883aa94c2dc8825dd4d52625f61a8e021bb45f.png?mw=700" alt="smb-on-docker-desktop-01-03.png" /></a></li> <li>ネットワークアダプタ → Microsoft → Microsoft KM-TEST Loopback Adapter を選択<br /> <a href="https://crieit.now.sh/upload_images/613a8016ee1018286cefefa98677cfb861a8e02c2da1c.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/613a8016ee1018286cefefa98677cfb861a8e02c2da1c.png?mw=700" alt="smb-on-docker-desktop-01-04.png" /></a> <a href="https://crieit.now.sh/upload_images/8ac078e306cc9ccf4c86e0f682b0523461a8e03adbf50.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/8ac078e306cc9ccf4c86e0f682b0523461a8e03adbf50.png?mw=700" alt="smb-on-docker-desktop-01-05.png" /></a></li> <li>ネットワーク接続の一覧 (Win+R で <code>ncpa.cpl</code> を実行) を開き、 今作成した 仮想NIC のプロパティを開く。<br /> <a href="https://crieit.now.sh/upload_images/5b8de4d5d6a36c6c2a4d494d1a8df3c561a8e03e4f763.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/5b8de4d5d6a36c6c2a4d494d1a8df3c561a8e03e4f763.png?mw=700" alt="smb-on-docker-desktop-01-06.png" /></a></li> <li>TCP/IPv4 のプロパティを開いて、 適当な固定 IPアドレスとサブネット (例として <code>192.168.254.2</code>) を設定する<br /> <a href="https://crieit.now.sh/upload_images/5ddc91e1d3d669965297caf67275d01e61a8e046bccb3.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/5ddc91e1d3d669965297caf67275d01e61a8e046bccb3.png?mw=700" alt="smb-on-docker-desktop-01-07.png" /></a> <a href="https://crieit.now.sh/upload_images/85747f1bd260d98415c5c25e3b3f851861a8e04b05d16.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/85747f1bd260d98415c5c25e3b3f851861a8e04b05d16.png?mw=700" alt="smb-on-docker-desktop-01-08.png" /></a></li> <li>管理者権限でターミナル (コマンドプロンプトや PowerShell) を立ちあげ、 netsh コマンドでポートプロキシを立ちあげる。 <ul> <li>以下は、 仮想NIC の固定 IP に <code>192.168.254.2</code> を設定し、プロキシ先のポートを 38445 番にする場合。<br /> <code>powershell netsh interface portproxy add v4tov4 listenport=445 listenaddress=192.168.254.2 connectport=38445 connectaddres=127.0.0.1</code><br /> <a href="https://crieit.now.sh/upload_images/ad7b283d74cbfdf38529ec95c1e4ed0d61a8e04dd4caf.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/ad7b283d74cbfdf38529ec95c1e4ed0d61a8e04dd4caf.png?mw=700" alt="smb-on-docker-desktop-01-09.png" /></a></li> </ul></li> <li><strong>PC を再起動</strong> する</li> </ol> <p>これで準備完了だ。</p> <h3 id="SMB で使ってみる"><a href="#SMB+%E3%81%A7%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">SMB で使ってみる</a></h3> <p>冒頭に紹介した、以前の記事の Dockerfile を使って、 SMB を立ちあげてみる。</p> <p><gist src="https://gist.github.com/advanceboy/a315d83d900929103d858a461b673e52.js"></gist></p> <p>この Dockerfile のあるディレクトリをカレントディレクトリにして、以下を実行する。</p> <pre><code class="powershell">docker build -t simple-samba . docker run --rm -p 38445:445 simple-samba </code></pre> <p>実用的には、 docker run の <code>-v</code> オプションなどで、適当なボリュームをマウントする感じになるだろう。</p> <p>そして、コンテナを起動した状態で ループバックアダプター の 仮想NIC に設定したアドレス (上記の例だと <code>\\192.168.254.2\</code>) に Windows エクスプローラー からアクセスできれば成功だ。</p> <p><a href="https://crieit.now.sh/upload_images/da0ed041118e80d7855560a1e6bca04e61a8e050c18c7.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/da0ed041118e80d7855560a1e6bca04e61a8e050c18c7.png?mw=700" alt="smb-on-docker-desktop-02-01.png" /></a></p> <h2 id="うまく動かない場合"><a href="#%E3%81%86%E3%81%BE%E3%81%8F%E5%8B%95%E3%81%8B%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88">うまく動かない場合</a></h2> <p>うまく動かない場合、 portproxy を提供する <code>iphlpsvc</code> (IP Helper) サービス が、 445 ポートをリッスンできているか調べてみよう。</p> <p><code>netstat</code> コマンドで、 192.168.254.2:445 をリッスンしているプロセスID を調べる。<br /> そして、その プロセスID が何のサービスなのか、 Windows PowerShell v5.1<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Get-WmiObject Win32_Service から確認してみよう。</p> <p>うまく動作していれば、以下のように <code>iphlpsvc</code> サービス であることが確認できるだろう。</p> <pre><code class="plain">PS > netstat -ano | findstr 445 TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4 TCP 0.0.0.0:8445 0.0.0.0:0 LISTENING 13944 TCP 192.168.254.2:445 0.0.0.0:0 LISTENING 4016 TCP 192.168.254.2:60665 192.168.254.2:445 ESTABLISHED 4 PS > Get-WmiObject Win32_Service | ? ProcessId -EQ 4016; ExitCode : 0 Name : iphlpsvc ProcessId : 4016 StartMode : Auto State : Running Status : OK </code></pre> <p>もし、 192.168.254.2:445 をリッスンしているプロセスID が 4 だった場合、 OS の <code>LanmanServer</code> サービスに関係するカーネルプロセスがこのポートをふさいでしまっているため、 portproxy が正しく動作していないと言うことになる。</p> <pre><code class="plain">PS > netstat -ano | findstr 445 TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4 TCP 0.0.0.0:8445 0.0.0.0:0 LISTENING 13944 TCP 192.168.254.2:445 192.168.254.2:60665 ESTABLISHED 4 TCP 192.168.254.2:60665 192.168.254.2:445 ESTABLISHED 4 </code></pre> <p>これは、おそらく portproxy を機能させる <code>iphlpsvc</code> サービスが機能する前に、 <code>LanmanServer</code> サービスが 445 ポートを塞いでしまっているからだと考えられる。</p> <p>確実ではないと思われるものの、 <code>iphlpsvc</code> サービスが先に機能するかもしれない対策を、いくつか紹介する。<br /> いずれも、設定後 PC の再起動が望ましい。</p> <ul> <li>Win+R で「ファイルを指定して実行」を開き、 <code>services.msc</code> を実行して、 「サービス」 の管理コンソールを立ちあげ、 "IP Helper" (<code>iphlpsvc</code>) のスタートアップが「自動」 になっていることを確認する。 <ul> <li>管理者権限で PowerShell を立ちあげ、 以下のコマンドを実行するのでも OK<br /> <code>Set-Service iphlpsvc -StartupType Automatic;</code></li> </ul></li> <li>netsh で IPv6 のサポートを追加する <ul> <li>管理者権限でターミナル (コマンドプロンプトや PowerShell) を立ちあげ、 netsh コマンドで以下のように実行する。<br /> <code>netsh interface ipv6 install</code></li> <li>理由がよくわからないが、これで上手くいく場合があるらしい。<br /> <a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/24646165/netsh-port-forwarding-from-local-port-to-local-port-not-working">portforwarding - NETSH port forwarding from local port to local port not working - Stack Overflow</a></li> </ul></li> <li><code>LanmanServer</code> サービスの起動を遅延させる: <ul> <li>管理者権限で PowerShell を立ちあげ、 <code>LanmanServer</code> サービスの起動を「手動」にして起動を遅延させる。<br /> <code>Set-Service LanmanServer -StartupType Manual;</code></li> <li>設定の → アカウント → サインイン オプション → 「更新または再起動の後にサインイン情報を使ってデバイスのセットアップを自動的に完了します。」 の on, off を切り替えてみる。</li> <li>ただし、 off にすると OS 再起動時のログイン速度が遅くなる。</li> </ul></li> <li>コントロール パネル → ネットワークとインターネット → ネットワークと共有センター → 共有の詳細設定 で、 仮想NIC が属するプロファイル (ゲストまたはパブリック) で、 「ファイルとプリンターの共有を無効にする」 を選択する。 <ul> <li>当然、ゲストまたはパブリックネットワークへ繋いだときに、ファイル共有ができなくなる。</li> </ul></li> </ul> <p>どうしても 仮想NIC の 445 ポートが PID 4 に奪われる場合、 <code>iphlpsvc</code> サービスと <code>LanmanServer</code> サービスの起動順とかを見てみると良いかもしれないが…<br /> 確認したところで何か具体的な対策があるわけでは無いが…</p> <pre><code>$procs = Get-WmiObject Win32_Service -Filter "Name='iphlpsvc' or Name='LanmanServer'"; Get-WmiObject win32_process -Filter (($procs.ProcessId | %{ "ProcessId='$_'" }) -join ' or ') | select Name,CreationDate,ProcessId,@{Name='Service'; Exp={$procs | ? ProcessId -eq $_.ProcessId | select -exp Name<span>}</span><span>}</span>; </code></pre> <h2 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h2> <p>後半、動作しない場合の対策についてつらつらと書いてしまったが、ちゃんと動きさえすればなかなか便利なはずだ。</p> <p>明日、 <a target="_blank" rel="nofollow noopener" href="https://qiita.com/advent-calendar/2021/docker">docker Advent Calendar 2021</a> の 3日目 は… 今のところ空いているようだ。<br /> どなたか書いてみてはいかがだろう?</p> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>2021年現在、 PowerShell v7 系列だと <code>Get-WmiObject</code> コマンドが動かないため。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> advanceboy