TL;DR
背景
遊休パーツがあったので、ubuntuマシンを1台組んだ。
今後、環境構築は死ぬほどやりたくなかったので、
dockerにて管理することにした。この記事はその時の備忘録となる。
ラズパイで動いていたもの、AWSで動いていたもの、ここで一元管理したい。
リスク分散?知らないな....
前提とか
ホストマシンのOS
Ubuntu 24.04 LTS
作るコンテナで何をするつもり?
- cronで指定時間にファイルをDLするスクリプトを実行する。
- sshで保存したファイルを見に行けるようにしておく。
1. 公式ドキュメントを読んでみる
ベストプラクティスのページを読んで考え方について把握しておく。
後でぐちゃぐちゃになった環境で困るのは自分だから。
ちなみに日本語化プロジェクトがあるので、最初はここを読むと良い気がする。
ベストプラクティス
Dockerfile を書くベストプラクティス — Docker-docs-ja 24.0 ドキュメント
理由、経緯は省略して、ここからいくつか引用する
不要なパッケージを入れることに関しては「禁止」とかなり強い言葉を使っており、
笑いそうになったが「とりあえずあったら便利だし入れとくか!」のようなナイーヴな考え方は捨てろと言っている。お前のことだぞ。(自戒)
(ちなみに以前のドキュメントには「不要なパッケージのインストールを避ける」と書いており、今よりだいぶ優しい。何があったんだ。)
以上を念頭において「あっ、俺が今やっていることは異常かもしれない」と自覚しながら作っていく。
2. NETWORKS作成
LAN内の他の端末からもアクセスしたかったため、
ブロードキャストドメインはホストマシンと同一にする。
設定にはmacvlanを使用する。
macvlan ネットワークの使用 — Docker-docs-ja 24.0 ドキュメント
ホストマシンが使用している物理ネットワークインタフェース名、subnet、gatewayをあらかじめメモしておく。
ip addr
上記でメモっておいた各種値を確認しながら、コンテナに使用するネットワーク設定を作成する。
docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=enp4s0 mynet
ここでmacvlanを使用して作成できるもののイメージは以下ページ引用
俺がここで何を言いたいのかというと、
ホストマシンとポートは共有しているため、外部とやり取りする場合はポートフォワード系のケアが必要
になるということ。
後述するssh設定では、コンテナ上のsshで使用するポートを変更しています。
3. Dockerfile作成
sshの設定を行う
ホストマシンでもsshを使用している場合、ポート変更は必須です。
RUN apt install openssh-server -y
# 使用するポートを2223へ変更
RUN sed -i 's/#*Port 22/Port 2223/' /etc/ssh/sshd_config
# 公開鍵認証を使用した接続を許可
RUN sed -i 's/#*PubkeyAuthentication [a-z]*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
# パスワードを使用した接続を許可
RUN sed -i 's/#*PasswordAuthentication [a-z]*/PasswordAuthentication yes/' /etc/ssh/sshd_config
ちなみに公開鍵認証を有効した場合、公開鍵は ~/.ssh/authorized_keys に置きましょう。
cronの設定を行う
# cron と nano
RUN apt install cron nano -y
# UTC であることに注意
RUN (crontab -l -u user; echo "00 16 * * 02 ur/file.sh")| crontab -u user -
なんか変な書き方してるので少し説明します。
オプション | 効果 |
---|---|
-l | 一覧出力 |
-u | 実行ユーザ指定 |
- | 標準入力受付 |
「一覧出力」 + 「echoで追記した文字列」を標準入力でcrontabに流し込む。
って感じです。
コンテナ起動時にssh/cronも起動させる
以下スクリプトを用意して、dockerfileの最後の方で実行するように書きます。
#!/bin/sh
# Start the ssh server
/etc/init.d/ssh start
# Start the cron
service cron start
# Execute the CMD
exec "$@"
# startup
COPY startup.sh /startup.sh
RUN chmod +x /startup.sh
ENTRYPOINT ["/startup.sh"]
CMD ["/bin/bash"]
これでコンテナ起動時にスクリプトが実行されます。
最後のCMDは、コンテナ起動後すぐに落ちてしまわないようにするためです。
コンテナはやることがなくなったら落ちるので。
完成したdockerfile
すこしずつ切り取られると理解しにくいと思うので一応全体を載せときます。
説明していない部分、伏せてる部分もあるので注意。
FROM ubuntu:latest
RUN apt update && apt dist-upgrade -y && apt autoremove
# add user
# パスワードは手動で設定が必要
ARG USERNAME=hxbdy
ARG GROUPNAME=hxbdy
ARG UID=1001
ARG GID=1001
RUN groupadd -g $GID $GROUPNAME && useradd -m -s /bin/bash -u $UID -g $GID $USERNAME
# apt install
# cron
RUN apt install cron nano -y
# ssh
RUN apt install openssh-server -y
# git
RUN apt install git -y
# SSH
# 鍵は手動で追加が必要
RUN sed -i 's/#*Port 22/Port 2222/' /etc/ssh/sshd_config
RUN sed -i 's/#*PubkeyAuthentication [a-z]*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
RUN sed -i 's/#*PasswordAuthentication [a-z]*/PasswordAuthentication yes/' /etc/ssh/sshd_config
# make workspace
ARG WORKSPACE=/home/$USERNAME/workspace
WORKDIR $WORKSPACE
RUN chmod 777 $WORKSPACE
USER $USERNAME
RUN git clone https://github.com/???/???.git
# cron
# UTC であることに注意
RUN (crontab -l -u hxbdy; echo "00 16 * * 02 $WORKSPACE/???.sh")| crontab -u hxbdy -
# startup
USER root
COPY startup.sh /startup.sh
RUN chmod +x /startup.sh
ENTRYPOINT ["/startup.sh"]
CMD ["/bin/bash"]
以上。ビルドして完成。
4. IMAGES作成
あらかじめ作成しておいていたネットワーク設定を使い、ホストマシン起動と同時にコンテナも実行するコマンドはこうだ~~~
docker run -it --name ubuntu --hostname="docker-ubuntu" --network mynet --ip 192.168.100.111 --restart unless-stopped ubuntu
疎通確認
windows powershellから確認した。
Test-NetConnection 192.168.100.111 -Port 2223
色々出てくるけど、
TcpTestSucceeded : True
となっていればOK
逆引き目次
コンテナ起動直後にスクリプトを実行したい
- dockerfileでENTRYPOINTを用意してスクリプトを指定する
sshできない
- ホストマシンと使用ポートがバッティングしている
- ユーザのパスワードを設定していない
- ユーザの公開鍵を置いていない
コンテナがすぐ落ちる
タイムゾーンを変更しても次回起動時UTCに戻ってしまう
- 諦める
- 自分はこっち。楽な方へ楽な方へ....
- cronなどはUTCで設定する。
- いやいやいや、なんとかしたい。