tag:crieit.net,2005:https://crieit.net/tags/alpine/feed
「alpine」の記事 - Crieit
Crieitでタグ「alpine」に投稿された最近の記事
2022-12-29T16:47:37+09:00
https://crieit.net/tags/alpine/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/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/17496
2021-07-11T01:08:30+09:00
2021-07-11T01:08:30+09:00
https://crieit.net/posts/listing-github-repository-in-docker-20210711
Github で特定ユーザの publicリポジトリ の名前の一覧を生成する Docker Compose
<h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2>
<p>自分のあるリポジトリを clone しようとして、名前を失念。探すのに手間取ったのでリポジトリの名前の一覧を生成するスクリプトが欲しくなりました。</p>
<h2 id="調査"><a href="#%E8%AA%BF%E6%9F%BB">調査</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/emergent/items/a557246a0c0bf9d50a11">GitHubのリポジトリを一覧化する(public/private両対応) - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://rcmdnk.com/blog/2017/10/03/computer-github/">GitHubのレポジトリ一覧を取ってくるワンライナー</a></li>
</ul>
<p>調べたら Linuxコマンド でどうにかなりそうだったので、 Docker で Linux環境 を用意してごにょごにょしよう、と思い立ちました。</p>
<h2 id="成果物"><a href="#%E6%88%90%E6%9E%9C%E7%89%A9">成果物</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/docker_list_of_hirokawa">GitHub - arm-band/docker_list_of_hirokawa: Github の特定ユーザの public リポジトリの一覧を生成する Docker Compose 設定集。</a></li>
</ul>
<h2 id="構成"><a href="#%E6%A7%8B%E6%88%90">構成</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>PROJECT_ROOT/
├ docker/
│ └ Dockerfile
│
├ entrypoint/
│ └ entrypoint.sh
│
├ template/
│ └ script.sh // コンテナ内で実行したいスクリプトのテンプレート。一部変数をエントリポイントで置換
│
├ workspace/ // リポジトリ名一覧のテキストファイルのダンプ先
│
├ .env // docker-compose.yml 用の環境変数
└ docker-compose.yml
</code></pre>
<p>今回はこんなディレクトリ構造に。</p>
<h3 id="docker-compose.yml"><a href="#docker-compose.yml">docker-compose.yml</a></h3>
<pre><code class="yml">version: '3.8'
services:
hirokawa:
build:
context: ./docker
dockerfile: Dockerfile
args:
USER_NAME: $USER_NAME
FILE_NAME: $FILE_NAME
volumes:
# entrypoint
- ./entrypoint:/entrypoint
# workspace
- ./workspace:/workspace
# docker settings template
- ./template:/template
tty: true
entrypoint: /bin/sh -c "/bin/sh /entrypoint/entrypoint.sh $USER_NAME $FILE_NAME && /bin/sh"
</code></pre>
<p>リポジトリ名の一覧を取得したい対象ユーザ名とダンプ先ファイル名を <code>.env</code> で指定しています。</p>
<h3 id=".env"><a href="#.env">.env</a></h3>
<pre><code class="env">USER_NAME=saigyo
FILE_NAME=repository_list.txt
</code></pre>
<p>上述の通り。</p>
<h3 id="docker/Dockerfile"><a href="#docker%2FDockerfile">docker/Dockerfile</a></h3>
<pre><code class="Dockerfile">FROM alpine:latest
RUN apk update && \
apk upgrade && \
apk add --no-cache \
jq \
bash \
sed \
curl
RUN mkdir /var/script
RUN chmod 777 /var/script
</code></pre>
<p>必要なパッケージのインストールとスクリプトの生成先のディレクトリの作成。</p>
<p>今回はやることが最小限なので alpine を使用。</p>
<h3 id="entrypoint/entrypoint.sh"><a href="#entrypoint%2Fentrypoint.sh">entrypoint/entrypoint.sh</a></h3>
<pre><code class="sh">sed -e "s/USER_NAME/${1}/gi" -e "s/FILE_NAME/${2}/gi" /template/script.sh > /var/script/script.sh
</code></pre>
<p>一部変数名を <code>.env</code> の値で置換。一行しかないので command でも良かったかも。</p>
<h3 id="template/script.sh"><a href="#template%2Fscript.sh">template/script.sh</a></h3>
<pre><code class="sh">for page in $(seq 1 10);
do result=$(curl -s "https://api.github.com/users/USER_NAME/repos?page=$page&per_page=100"|jq -c '[.[] .name]'|jq -c '.[]');
if [ -z "$result" ];
then break;
fi;
formatted_result=$(echo "$result"|sed -e "s/\"//gi");
echo "$formatted_result" > "/workspace/FILE_NAME";
done
</code></pre>
<p>実行するスクリプトのテンプレート。個人ユーザ対象で <code>curl</code> で Github API を叩いて100個(指定可能な最大数)ずつ出力、 <code>jq</code> でフィルタリングして、 <code>workspace</code> にファイルとしてダンプ。</p>
<hr />
<p>これでやりたいことは実現できました。</p>
<h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2>
<h3 id="サンプル"><a href="#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB">サンプル</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/emergent/items/a557246a0c0bf9d50a11">GitHubのリポジトリを一覧化する(public/private両対応) - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://rcmdnk.com/blog/2017/10/03/computer-github/">GitHubのレポジトリ一覧を取ってくるワンライナー</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://deep.tacoskingdom.com/blog/11">[Shell script] Alpine LinuxのDockerコンテナ内で使うjqをインストールする方法</a></li>
</ul>
<h3 id="jq"><a href="#jq">jq</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://jqplay.org/#">jq play</a></li>
</ul>
<h2 id="alpine で bash"><a href="#alpine+%E3%81%A7+bash">alpine で bash</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yumenomatayume/items/b28edbaf40a293519b8a">【docker alpine linux】でbashの使用方法 - Qiita</a></li>
</ul>
<h3 id="starting container process caused: exec: "bash": executable file not found in $PATH: unknown"><a href="#starting+container+process+caused%3A+exec%3A+%26quot%3Bbash%26quot%3B%3A+executable+file+not+found+in+%24PATH%3A+unknown">starting container process caused: exec: "bash": executable file not found in $PATH: unknown</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://kaoru2012.blogspot.com/2017/11/docker-executable-file-not-found-in-path.html">プログラマーの雑記: docker コンテナにログイン時に、「executable file not found in $PATH」エラーの対応</a></li>
</ul>
<h3 id="alpineイメージ への entrypoint 指定"><a href="#alpine%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8+%E3%81%B8%E3%81%AE+entrypoint+%E6%8C%87%E5%AE%9A">alpineイメージ への entrypoint 指定</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://cpoint-lab.co.jp/article/202009/16844/">【Docker】ENTRYPOINT と CMD の仕組みと小技 – 株式会社シーポイントラボ | 浜松のシステム・RTK-GNSS開発</a></li>
</ul>
arm-band