2025/05/04 Updated by

Docker Image を自作する (2)

ubuntu 24.04LTS + 新規ユーザ + sshd


[Up] Japanese English

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

方針

作成手順

  1. 作業用フォルダを作成する
  2.   $ mkdir -p ~/doc/docker/ubuntu24_sshd
      $ cd ~/doc/docker/ubuntu24_sshd
    
  3. 作業用フォルダの中に 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=パスワード
    
    ENV SSHD_PORT=22
    
    # 必要なパッケージのインストール
    
    RUN apt-get update && \
        DEBIAN_FRONTEND=noninteractive apt-get install -y \
        sudo \
        bash \
        openssh-server \
        supervisor \
        && 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 && \
        sed -i "s/^#Port.*/Port ${SSHD_PORT}/" /etc/ssh/sshd_config && \
        mkdir /var/run/sshd
    
    
    # supervisord の設定ファイルを設置する (Daemon 起動用)
    
    RUN mkdir -p /var/log/supervisor
    COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
    
    
    # ポート開放
    
    EXPOSE 22
    
    
    # Copy Shell Script "entrypoint.sh"
    
    COPY entrypoint.sh /entrypoint.sh
    RUN chmod +x /entrypoint.sh
    
    ENTRYPOINT ["/entrypoint.sh"]
    
    CMD []
    
  5. 作業用フォルダの中に entrypoint.sh を作成する
  6. entrypoint.sh
    #!/bin/bash
    set -e
    
    if [ ! -f /var/app/.initialized ]; then
        ######## First Time ########
    
        echo "First run. Setting up ..."
        mkdir -p /var/app
        touch /var/app/.initialized
    
        # ユーザーが存在しない場合のみ作成する
        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
            usermod -aG sudo ${UNAME}
        fi
    
        # ホームディレクトリの Owner が root:root になることがあるので変更する。
        chown -v ${UNAME}:${UNAME}  /home/${UNAME}
    
        # SSHD のポート番号を変更する
        sed -i "s/^Port.*/Port ${SSHD_PORT}/" /etc/ssh/sshd_config
        
    else
        ######## Second Time or Later ########
        
        echo "Starting for the second time or later ..."
    
    fi
    
    # supervisord start (background)
    /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf &
    
    # Execute Commands in CMD
    
    if [ "$#" -gt 0 ]; then
        exec "$@"
    else
        echo "No command provided. Starting bash ..."
        exec bash
    fi
    
  7. 作業用フォルダの中に supervisord.conf を作成する
  8. supervisord.conf
    # supervisord の設定ファイル
    
    [supervisord]
    nodaemon=true
    logfile=/var/log/supervisor/supervisord.log
    
    # sshd を起動する
    
    [program:sshd]
    command=/usr/sbin/sshd -D -e
    stdout_logfile=/var/log/sshd_stdout.log
    stderr_logfile=/var/log/sshd_stderr.log
    autostart=true
    autorestart=true
    
  9. Image を build する。
  10.   $ docker build -t ubuntu24-sshd .
      ...
    成功
    
  11. 生成した Image を確認する
  12. $ docker image ls
    REPOSITORY      TAG       IMAGE ID       CREATED         SIZE
    ubuntu24_sshd   latest    23164575e4d2   8 seconds ago   222MB
    
    ...
    

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 を生成する

Image ubuntu24_sshd のデフォルトのユーザ情報とSSHサーバ情報を用いて、 新しい Container ubuntu24-sshd を生成する。

  1. Image から Container を生成して起動する。ユーザ情報はデフォルト値 (guest) を利用する。 Container のファイルシステム内にホストOSのディレクトリをマウントする。 Container を起動するたびに、sshd サーバが起動される。
  2. $ docker run --name ubuntu24-sshd --restart always \
        -p 10022:22 \
        -v /home/docker/sshd:/mnt/hostos \
        -it ubuntu24_sshd
    
    起動オプション
  3. Container を起動した対話環境が、そのまま Container 内で動作する bash との対話環境になる。root権限でloginした状態である。
  4. First run. Setting up ...       ← 生成された Container 内で entrypoint.sh が実行される
    Creating group guest with GID=3000
    Creating user guest with UID=3000, GID=3000
    ownership of '/home/guest' retained as guest:guest
    No command provided. Starting bash ...
    root@af401d3cdf85:/# 2025-05-11 09:32:40,710 CRIT Supervisor is running as root.  Privileges were not dropped because no user is specified in the config file.  \
    If you intend to run as root, you can set user=root in the config file to avoid this message.
    2025-05-11 09:32:40,711 INFO supervisord started with pid 38
    2025-05-11 09:32:41,715 INFO spawned: 'sshd' with pid 41
    2025-05-11 09:32:42,717 INFO success: sshd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
    #              ← Container 内の対話環境 (root権限の bash) が動く
    
  5. (Container 内で) ホストOSのマウントポイントを調べる。
  6. # ls -ld /mnt/hostos
    drwxr-xr-x 2 root root 4096 May 11 09:32 /mnt/hostos
    
  7. (Container 内で) 新規ユーザのホームディレクトリを調べる。
  8. # ls -ld /home/guest
    drwxr-x--- 2 guest guest 4096 May 11 09:32 /home/guest
    # ls -la /home/guest
    total 20
    drwxr-x--- 2 guest guest 4096 May 11 09:32 .
    drwxr-xr-x 1 root  root  4096 May 11 09:32 ..
    -rw-r--r-- 1 guest guest  220 Mar 31  2024 .bash_logout
    -rw-r--r-- 1 guest guest 3771 Mar 31  2024 .bashrc
    -rw-r--r-- 1 guest guest  807 Mar 31  2024 .profile
    
  9. (Container 内で) Control-P と Control-Q を順にタイプして、ホストOSの対話環境に戻る。 Container 内のシェルは動作したままとなる。
  10. # ^p ^q                ← Container の対話環境を抜ける
    $              ← ホストOS 内の対話環境に戻る
    
  11. ホストOSにおいて、Container からマウントされているディレクトリを調べる。
  12. $ ls -ld /home/docker/sshd
    drwxr-xr-x 2 root root 4096  5月 11 18:32 /home/docker/sshd
    
  13. ホストOSから、Continer の guest ユーザのアカウントに ssh でアクセスする。
  14. $ ssh -p 10022 guest@localhost ← ホストOSの 10022 番ポートに sshアクセスする ... Are you sure you want to continue connecting (yes/no/[fingerprint])? yes ... guest@localhost's password: パスワードを入力する。エコーバックされない。
    Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.11.0-25-generic x86_64) ... guest % ← Container 内の guest 権限の対話環境が開始する
  15. (Container 内の guest 権限で) ホームディレクトリを表示する。
  16. $ pwd
    /home/guest
    
  17. (Container 内の guest 権限で) ホームディレクトリにあるファイルの一覧を表示する。
  18. $ ls -la
    total 24
    drwxr-x--- 3 guest guest 4096 May 11 09:35 .
    drwxr-xr-x 1 root  root  4096 May 11 09:32 ..
    -rw-r--r-- 1 guest guest  220 Mar 31  2024 .bash_logout
    -rw-r--r-- 1 guest guest 3771 Mar 31  2024 .bashrc
    drwx------ 2 guest guest 4096 May 11 09:35 .cache
    -rw-r--r-- 1 guest guest  807 Mar 31  2024 .profile
    
  19. (Container 内の guest 権限で) パスワードを変更する。
  20. $ passwd
    Changing password for guest.
    Current password:               ← パスワード を入力する。
    New password:                   ← 新しいパスワード を入力する。
    Retype new password:            ← もう一度新しいパスワード を入力する。
    passwd: password updated successfully
    
  21. (Container 内の guest 権限で) ssh 経由の対話環境を終了する。
  22. guest@af401d3cdf85:~$ exit logout
    Connection to localhost closed. $
  23. (ホストOS上) docker 上の実行中の container の状態を調べる
  24. $ docker container ls
    CONTAINER ID   IMAGE           COMMAND            CREATED         STATUS         PORTS                                       NAMES
    af401d3cdf85   ubuntu24_sshd   "/entrypoint.sh"   4 minutes ago   Up 4 minutes   0.0.0.0:10022->22/tcp, [::]:10022->22/tcp   ubuntu24-sshd
    
  25. (ホストOS上) docker 上のすべての(停止中を含む) container の状態を調べる
  26. $ docker container ls -a
    CONTAINER ID   IMAGE           COMMAND            CREATED         STATUS         PORTS                                       NAMES
    af401d3cdf85   ubuntu24_sshd   "/entrypoint.sh"   4 minutes ago   Up 4 minutes   0.0.0.0:10022->22/tcp, [::]:10022->22/tcp   ubuntu24-sshd
    
  27. (ホストOS上) docker 上の Image の一覧を表示する。
  28. $ docker image ls
    REPOSITORY      TAG       IMAGE ID       CREATED             SIZE
    ubuntu24_sshd   latest    23164575e4d2   About an hour ago   222MB
    ubuntu24-user   latest    7b64f0b8bea1   3 hours ago         81.4MB
    
  29. (ホストOS上) 外部のPCからネットワーク経由で Container にアクセスするためには、ホストOSの 10022 番ポートを開けておく必要がある。
  30. Docker の公式文書では、「docker のポートフォワーディングは ufw のフィルタリングよりも前に行わるために、ufw の影響を受けない」 と記述されている (2025年春時点) が、これは現時点では間違いのようだ。 Containerに外部からアクセスするためには、ホストOSのポートを開けておく必要がある。

    Ubuntu 24.04LTS の場合: ufw を用いる
    1. (ホストOS上) ファイアウォール ufw を有効化する。(既に有効化してあれば必要なし)
    2.   $ sudo apt update                       ← aptのデータベースを更新する
        $ sudo apt install -y ufw               ← ufw をインストールする。
        $ sudo systemctl enable ufw               ← ufw を有効化する
        $ sudo systemctl restart ufw               ← ufw を再起動する
        
    3. (ホストOS上) ホストOSの 10022 番ポートを開放する。
    4.   $ sudo ufw allow 10022                       ← 10022 番ポートを開放する
        ルールを追加しました
        ルールを追加しました (v6)
        
    5. (ホストOS上) ファイアウォールの状態を確認する。
    6.   $ sudo ufw status 10022                       ← 10022 番ポートを開放する
        ...
      状態: アクティブ
      
      To                         Action      From
      --                         ------      ----
      ...
      10022                      ALLOW       Anywhere
      ...
      10022 (v6)                 ALLOW       Anywhere (v6)
        ...
      
  31. (ネットワーク上の他のPC) 他のマシンから、ホストOS上の Container に ssh 接続する。
  32. 以下は、ホストOSの IPアドレスが 192.168.12.3 の場合の、ssh アクセスの様子である。

    (他のPCから) $ ssh -p 10022 guest@192.168.12.3 guest@192.168.12.3's password: ← パスワードを入力する。エコーバックされない。
    Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.11.0-25-generic x86_64) ... guest $ whoami ← Container に guest 権限でアクセスできる guest guest $ exit logout
    Connection to 192.168.12.3 closed. $