2025/05/03 Updated by

Docker Image を自作する

ubuntu 24.04LTS, sshd, httpd


[Up] Japanese English

sshd, httpd が自動起動する ubuntu24.04LTS の docker Image を生成する

方針

作成手順

  1. 作業用フォルダを作成する
  2.   $ mkdir -p ~/doc/docker/ubuntu24_sshd_httpd
      $ cd ~/doc/docker/ubuntu24_ssd_httpd
    
  3. 作業用フォルダの中に Dockerfile を作成する。Dockerfile中の パスワード の部分は、推測されにくい文字列に必ず変更すること。
  4. 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 []
    
  5. 作業用フォルダの中に supervisord.conf を作成する
  6. 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
    
  7. 作業用フォルダの中に entrypoint.sh を作成する
  8. 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
    
  9. Image を build する。
  10.   $ docker build -t ubuntu24-sshd-httpd .
      ...
    成功
    
  11. 生成した Image を確認する
  12. $ 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 を生成する。

  1. image から container を生成して起動する。 下の実行例はユーザ名を www とした場合であり、 自分の環境に合わせて適切な値に変更して指定すること。
  2.   $ 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
    
    起動オプション
  3. Container からマウントされるホスト OS の /home/docker/httpd が存在しない場合は、 "docker run" を実行したユーザの権限で作成される。
  4. $ ls -ld /home/docker/httpd
    drwxr-xr-x 2 nitta nitta 4096  5月  2 16:08 /home/docker/httpd
    
  5. ホストOS から、ssh を用いてゲストOS にアクセスする。
  6. $ 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
    $
    
  7. (ゲストOS上で)ホームディレクトリを調べる。
  8. (ゲストOS上で)
    $ pwd            ← ホームディレクトリのパスを表示する。
    /home/www
    $ ls -l          ← ホームディレクトリの情報を表示する。
    total 4
    drwxr-xr-x 2 www www 4096 May  2 07:28 doc            ← ホストOSの /home/docker/httpd にマウントされている
    
  9. (ゲストOS上で) パスワードを変更する
  10. $ passwd
    Changing password for www.
    Current password: パスワード ← エコーバックされない
    New password:  新しいパスワード(長いバージョン) ← エコーバックされない
    Retype new password:  新しパスワード ← エコーバックされない
    passwd: password updated successfully
    
  11. (ゲストOS上で) プロセスがどのユーザ権限で動いているか調べる。
  12. $ 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
    
  13. (ゲストOS上で) シェルを終了する。
  14. $ exit
    Connection to localhost closed.
    nitta@um580:~/doc/docker$ 
    
  15. Container に port forwarding するホストOSのポートを開放する。 ホストOSにより方法は異なるが、 以下はホストOSが Ubuntu 24.04LTS の場合。
  16. $ 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 内部ネットワークの調査

  1. ホストOSとは異なるマシンでブラウザを立ち上げて、Container ubuntu24-httpd 上のWWWサーバにアクセスする。
  2. URL は http://ホストOSのIPアドレス:21080/
  3. Container ubuntu24-httpd に ssh アクセスする。
  4. $ 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)
    ...
    $
    
  5. WWWサーバのlogを表示する。← すべてのWWWアクセスが 172.17.0.1 からになっていることがわかる
  6. $ 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/" ...
    
  7. ネットワークコマンドをインストールする
  8. まず、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
    
  9. netstat コマンドを用いて、ルーティング情報を調べる。 → Container が接続しているネットワークは 172.17.0.0/16で、 デフォルトのルーティング先が 172.17.0.1 であることがわかる
  10. $ 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
    
  11. ifconfig でContainer のIPアドレスを調べる。 → 172.17.0.2 であることがわかる。
  12. $ 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通りあるようだ。

Docker Contaner を生成する (2)

上記の「1Docker Contaner を生成する (1)」に対して、以下の変更を加える。