2025/05/03 Updated by 
Docker Image を自作する
ubuntu 24.04LTS, sshd, httpd
[Up]

sshd, httpd が自動起動する ubuntu24.04LTS の docker Image を生成する
方針
- ホストOS は Ubuntu 24.04LTS
- ゲストOS も Ubuntu 24.04LTS
- ユーザ情報は Container を生成するときに指定する。(省略可能)
- sshd を自動起動する。
- httpd を自動起動する。
- サーバーは supervisord を用いてバックグラウンドで起動する。
- Container 生成時にコマンドが与えられた場合は、フォアグラウンドで実行する。
- 生成する Docker Image 名は ubuntu24-sshd-httpd
作成手順
- 作業用フォルダを作成する
$ mkdir -p ~/doc/docker/ubuntu24_sshd_httpd
$ cd ~/doc/docker/ubuntu24_ssd_httpd
- 作業用フォルダの中に Dockerfile を作成する。Dockerfile中の パスワード の部分は、推測されにくい文字列に必ず変更すること。
Dockerfile |
# ゲストOS: Ubuntu 24.04 LTS
FROM ubuntu:24.04
# Change Your Own UNAME, UID, GID, PASS
ENV UNAME=guest
ENV UID=3000
ENV GID=3000
ENV PASS=パスワード
# 必要なパッケージのインストール
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
sudo \
openssh-server \
supervisor \
apache2 \
libapache2-mod-php \
php-fpm \
&& rm -rf /var/lib/apt/lists/*
# SSH 設定: パスワード認証を有効化
RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && \
mkdir /var/run/sshd
# Apache 設定: ServerName エラー防止
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
# PHP 設定
RUN sed -i 's/^;date\.timezone =.*/date\.timezone = "Asia\/Tokyo"/' /etc/php/8.3/apache2/php.ini
# PHP-FPM によるPHPの高速化
RUN sed -i '/<\/VirtualHost>/i <FilesMatch "\\.php$">\n SetHandler "proxy:unix:/var/run/php/php8.3-fpm.sock|fcgi://localhost/"\n</FilesMatch>' /etc/apache2/sites-available/default-ssl.conf
RUN a2enmod proxy_fcgi setenvif
RUN a2enconf php8.3-fpm
# supervisord の設定ファイルを設置する (Daemon 起動用)
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# ポート開放
EXPOSE 22 80
# Copy Shell Script "entrypoint.sh"
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD []
|
- 作業用フォルダの中に supervisord.conf を作成する
supervisord.conf |
# supervisord の設定ファイル
[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log
[program:sshd]
command=/usr/sbin/sshd -D
autostart=true
autorestart=true
[program:php-fpm]
command=/usr/sbin/php-fpm8.3 -F
autostart=true
autorestart=true
stdout_logfile=/var/log/php-fpm.log
stderr_logfile=/var/log/php-fpm.err
[program:apache2]
command=/usr/sbin/apachectl -D FOREGROUND
autostart=true
autorestart=true
|
- 作業用フォルダの中に entrypoint.sh を作成する
entrypoint.sh |
#!/bin/bash
set -e
# ユーザーが存在しない場合のみ作成する
if id "${UNAME}" &>/dev/null; then
echo "User ${UNAME} already exists. Skipping creation."
else
# 同名グループが無ければ作成
if ! getent group "${UNAME}" &>/dev/null; then
echo "Creating group ${UNAME} with GID=${GID}"
groupadd -g ${GID} ${UNAME}
else
echo "Group ${UNAME} already exists. Skipping group creation."
fi
echo "Creating user ${UNAME} with UID=${UID}, GID=${GID}"
useradd -m -u ${UID} -g ${GID} -s /bin/bash ${UNAME}
echo "${UNAME}:${PASS}" | chpasswd
adduser ${UNAME} sudo
fi
# ホームディレクトリの Owner を明示的に設定する
chown -v ${UNAME}:${UNAME} /home/${UNAME}
# supervisord start (background)
/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf &
# Execute Commands in CMD
if [ "$#" -gt 0 ]; then
exec "$@"
else
wait
fi
|
- Image を build する。
$ docker build -t ubuntu24-sshd-httpd .
...
成功
- 生成した Image を確認する
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu24-sshd-httpd latest 0db0d49bb9ee About a minute ago 431MB
ubuntu24-sshd-user latest 081475092073 22 hours ago 334MB
Container 用の永続的なファイルシステムを作成する
コンテナに永続的なファイルシステムを提供するために、1777 のパーミッションでフォルダを作っておく。
skicky bit が on (1777) のフォルダには、
「誰でもファイルを作成できるが、作成した本人だけがファイルを変更したり消したりできる」
という特徴がある。
$ sudo mkdir -p /home/docker ← ディレクトリを作成する
$ sudo chmod 1777 /home/docker ← 誰でもファイルを作成できるが、作成した本人にしか消去できないモードに設定する
$ ls -ld /home/docker ← ディレクトリのsticky bit が on になっていることを確認する。
drwxrwxrwt 3 root root 4096 4月 26 15:47 /home/docker
Docker Contaner を生成する (1)
Image ubuntu24-sshd-httpd で、ユーザ情報を指定して、
新しい Container
ubuntu24-httpd
を生成する。
- image から container を生成して起動する。
下の実行例はユーザ名を www とした場合であり、
自分の環境に合わせて適切な値に変更して指定すること。
$ docker run --name ubuntu24-httpd \
-e UNAME=www -e UID=2000 -e GID=2000 -e PASS=新しいパスワード \
--restart always \
-p 21022:22 -p 21080:80 -p 210443:443 \
-v /home/docker/httpd:/home/www/doc -it ubuntu24-sshd-httpd
起動オプション
- --name: 生成するcontainer の名前は ubuntu24-httpd
- -e: run 時に実行されるシェルスクリプト (entrypoint.sh) 中の環境変数を設定する。
環境変数名 | 値 |
UNAME | www |
UID | 2000 |
GID | 2000 |
PASS | 新しいパスワード |
- --restart: docker が起動すると、このコンテナも自動起動する。
- -p: ホストOSのポートへのアクセスをContainerのポートに forwarding する。
ポート番号 |
ホストOS | ゲストOS |
21022 | 22 |
21080 | 80 |
21443 | 443 |
- -v: ホストOSの /home/docker/httpd が Container の/home/www/httpd にマウントされる。
マウントポイント |
ホストOS | ゲストOS |
/home/docker/httpd | /home/www/doc |
- 使用する Docker Image は ubuntu24-sshd-httpd
- Container からマウントされるホスト OS の /home/docker/httpd が存在しない場合は、
"docker run" を実行したユーザの権限で作成される。
$ ls -ld /home/docker/httpd
drwxr-xr-x 2 nitta nitta 4096 5月 2 16:08 /home/docker/httpd
- ホストOS から、ssh を用いてゲストOS にアクセスする。
$ ssh -p 21022 www@localhost
www@localhost's password: パスワード ← エコーバックされない
(ゲスト OS のシェルが起動する)
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.10.14-linuxkit x86_64)
...
Last login: Fri May 2 07:29:20 2025 from 172.17.0.1
$
- (ゲストOS上で)ホームディレクトリを調べる。
(ゲストOS上で)
$ pwd ← ホームディレクトリのパスを表示する。
/home/www
$ ls -l ← ホームディレクトリの情報を表示する。
total 4
drwxr-xr-x 2 www www 4096 May 2 07:28 doc ← ホストOSの /home/docker/httpd にマウントされている
- (ゲストOS上で) パスワードを変更する
$ passwd
Changing password for www.
Current password: パスワード ← エコーバックされない
New password: 新しいパスワード(長いバージョン) ← エコーバックされない
Retype new password: 新しパスワード ← エコーバックされない
passwd: password updated successfully
- (ゲストOS上で) プロセスがどのユーザ権限で動いているか調べる。
$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4324 3208 pts/0 Ss+ 09:39 0:00 /bin/bash /entrypoint.sh
root 35 0.0 0.3 34516 27724 pts/0 S+ 09:39 0:00 /usr/bin/python3 /usr/bin/supervisord -c /etc/superviso
root 36 0.0 0.0 2800 1828 pts/0 S 09:39 0:00 /bin/sh /usr/sbin/apache2ctl -D FOREGROUND
root 37 0.0 0.0 12020 7976 pts/0 S 09:39 0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
root 39 0.0 0.0 6808 5508 pts/0 S 09:39 0:00 /usr/sbin/apache2 -D FOREGROUND
www-data 40 0.0 0.0 1999324 5048 pts/0 Sl 09:39 0:00 /usr/sbin/apache2 -D FOREGROUND
www-data 41 0.0 0.0 1999324 5208 pts/0 Sl 09:39 0:00 /usr/sbin/apache2 -D FOREGROUND
root 108 0.0 0.1 14432 10140 ? Ss 09:40 0:00 sshd: www [priv]
www 119 0.1 0.0 14692 6404 ? S 09:40 0:00 sshd: www@pts/2
www 120 0.0 0.0 2800 1708 pts/2 Ss 09:40 0:00 -sh
www 137 0.0 0.0 8280 4196 pts/2 R+ 09:48 0:00 ps aux
- (ゲストOS上で) シェルを終了する。
$ exit
Connection to localhost closed.
nitta@um580:~/doc/docker$
- Container に port forwarding するホストOSのポートを開放する。
ホストOSにより方法は異なるが、
以下はホストOSが Ubuntu 24.04LTS の場合。
$ sudo ufw status
$ sudo ufw allow 21022
$ sudo ufw allow 21080
$ sudo ufw allow 21443
Docker の内部ネットワークに関する注意
上記のように起動したContainer 上の WWW サーバでは、アクセスしてくるクライアントのIPアドレスを用いたアクセス制限がうまく動作しない。
その原因は、
「Docker ホストOS (172.17.0.1) がDocker内部ネットワーク(172.17.0.0/16)に対して NAPT をかけていて、
外部からのアクセスがすべて 172.17.0.1 からに見える」
である。
Docker 内部ネットワークの調査
- ホストOSとは異なるマシンでブラウザを立ち上げて、Container ubuntu24-httpd 上のWWWサーバにアクセスする。
URL は http://ホストOSのIPアドレス:21080/
- Container ubuntu24-httpd に ssh アクセスする。
$ ssh -p 21022 www@localhost
www@localhost's password: パスワード ← エコーバックされない
(ゲスト OS のシェルが起動する)
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.10.14-linuxkit x86_64)
...
$
- WWWサーバのlogを表示する。← すべてのWWWアクセスが 172.17.0.1 からになっていることがわかる
$ sudo tail /var/log/apache2/access.log
...
172.17.0.1 - - [04/May/2025:05:10:49 +0000] "GET /work2/ HTTP/1.1" 200 21202 "http://ホストOSのIPアドレス:21080/" ...
172.17.0.1 - - [04/May/2025:05:10:53 +0000] "GET /work3/ HTTP/1.1" 200 21202 "http://ホストOSのIPアドレス:21080/" ...
- ネットワークコマンドをインストールする
まず、aptのデータベースを更新しておいて
$ sudo apt update
ifconfig, netstat, arp をインストールする
$ sudo apt install -y net-tools
traceroute をインストールする
$ sudo apt install -y iputils-tracepath traceroute
ping をインストールする
$ sudo apt install -y iputils-ping
curl をインストールする
$ sudo apt install -y curl
ip をインストールする
$ sudo apt install -y iproute2
netstat
コマンドを用いて、ルーティング情報を調べる。
→
Container が接続しているネットワークは 172.17.0.0/16で、
デフォルトのルーティング先が 172.17.0.1 であることがわかる
$ netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
ifconfig
でContainer のIPアドレスを調べる。
→ 172.17.0.2 であることがわかる。
$ ifconfig
eth0: flags=4163 mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether xx:xx:xx:xx:xx:xx txqueuelen 0 (Ethernet)
RX packets 57700 bytes 10953734 (10.9 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 56874 bytes 6131126 (6.1 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73 mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
対策
対策は2通りあるようだ。
- Container を --net=host モードで起動する(ホストOSがLinuxの場合に限る) 。
ただし、Container がホストOSのネットワークを共有するため、-p
で指定した
port forwarding 機能は無視される。
- reverse proxy (nginxなど)を使って X-Forwarded-For を渡す。
Docker Contaner を生成する (2)
上記の「1Docker Contaner を生成する (1)」に対して、以下の変更を加える。
- Container の起動オプションで
-p
オプションは指定しない。
- Container の起動オプションに
--net=host
オプションを追加する。
- Conatiner がホストOSとネットワークを共有するために、ポート番号の衝突が問題になる。
- 次の方針でポートを外部に公開する。'x' は「未使用」, '*' は 「otherwise」 を意味する。
service | ポート番号 | ホストOS | Container |
ssh | 22 | 22 | 20022 |
http | 80 | x | 80 |
https | 443 | x | 443 |
rdp | 3389 | 3389 | x |
* | * | * | x |
- Container の sshd の待ち受けポート番号を変更する必要がある。