このページ内での表記:「ホストOSの対話環境」は背景色を黄色(lightyellow)で表す。「Conainer 内の root 権限の対話環境」は背景色を水色(azure)であらわす。「Conainer 内の一般ユーザ権限の対話環境」は背景色を赤色(#ffeeee)であらわす。「他のPCの対話環境」は紫色(#eeeeff)で表す。
$ mkdir -p ~/doc/docker/ubuntu24_sshd_httpd $ cd ~/doc/docker/ubuntu24_ssd_httpd
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 \ apache2 \ libapache2-mod-php \ php-fpm \ net-tools iputils-tracepath traceroute iputils-ping curl iproute2 \ && rm -rf /var/lib/apt/lists/* # SSH 設定: パスワード認証を有効化 RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \ sed -i "s/^#Port.*/Port ${SSHD_PORT}/" /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 [] |
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 adduser ${UNAME} sudo 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/supervisord.conf & # Execute Commands in CMD if [ "$#" -gt 0 ]; then exec "$@" else echo "No command provided. Starting bash ..." exec bash fi |
supervisord.conf |
# supervisord の設定ファイル [supervisord] nodaemon=true [program:sshd] command=/usr/sbin/sshd -D -e autostart=true autorestart=true stdout_logfile=/var/log/sshd_stdout.log stderr_logfile=/var/log/sshd_stderr.log [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 stopasgroup=true killasgroup=true stdout_logfile=/var/log/apache2_stdout.log stderr_logfile=/var/log/apache2_stderr.log |
$ docker build -t ubuntu24_sshd_httpd . ... 成功
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu24_sshd_httpd latest 534506433e64 7 minutes ago 316MB ...
[参考] 標準の /etc/supervisor/supervisord.conf |
; supervisor config file [unix_http_server] file=/var/run/supervisor.sock ; (the path to the socket file) chmod=0700 ; sockef file mode (default 0700) [supervisord] logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) ; the below section must remain in the config file for RPC ; (supervisorctl/web interface) to work, additional interfaces may be ; added by defining them in separate rpcinterface: sections [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket ; The [include] section can just contain the "files" setting. This ; setting can list multiple files (separated by whitespace or ; newlines). It can also contain wildcards. The filenames are ; interpreted as relative to this file. Included files *cannot* ; include files themselves. [include] files = /etc/supervisor/conf.d/*.conf |
コンテナに永続的なファイルシステムを提供するために、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
Image ubuntu24_sshd_httpd を用いて、 新しい Container ubuntu24-httpd を生成する。
$ docker run --name ubuntu24-httpd --restart always \ -e UNAME=www \ -p 11022:22 -p 11080:80 -p 11443:443 \ -v /home/docker/httpd:/mnt/hostos \ -it ubuntu24_sshd_httpd起動オプション
環境変数名 | 値 |
---|---|
UNAME | www |
ポート番号 | |
---|---|
ホストOS | ゲストOS |
11022 | 22 |
11080 | 80 |
11443 | 443 |
マウントポイント | |
---|---|
ホストOS | ゲストOS |
/home/docker/httpd | /mnt/hostos |
First run. Setting up ... ← 生成された Container 内で entrypoint.sh が実行される Creating group www with GID=3000 Creating user www with UID=3000, GID=3000 info: Adding user `www' to group `sudo' ... ownership of '/home/www' retained as www:www No command provided. Starting bash ... 2025-05-12 12:23:43,794 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-12 12:23:43,795 INFO supervisord started with pid 40 2025-05-12 12:23:44,799 INFO spawned: 'apache2' with pid 43 2025-05-12 12:23:44,801 INFO spawned: 'php-fpm' with pid 44 2025-05-12 12:23:44,802 INFO spawned: 'sshd' with pid 45 2025-05-12 12:23:45,822 INFO success: apache2 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2025-05-12 12:23:45,823 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2025-05-12 12:23:45,823 INFO success: sshd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) # ← Container 内の対話環境 (root 権限の bash) が動く
# whoami root
# pwd /
# ls -ld /mnt/hostos drwxr-xr-x 2 root root 4096 May 12 12:04 /mnt/hostos
# ls -ld /home/www drwxr-x--- 2 www www 4096 May 12 12:23 /home/www # ls -la /home/www total 20 drwxr-x--- 2 www www 4096 May 12 12:23 . drwxr-xr-x 1 root root 4096 May 12 12:23 .. -rw-r--r-- 1 www www 220 Mar 31 2024 .bash_logout -rw-r--r-- 1 www www 3771 Mar 31 2024 .bashrc -rw-r--r-- 1 www www 807 Mar 31 2024 .profile
# ^p ^q ← Container内の対話環境で Control-P + Control-Q$ ← ホストOSの対話環境に戻る
$ ls -ld /home/docker drwxrwxrwt 6 root root 4096 5月 12 21:04 /home/docker # ls -la /home/docker 合計 24 drwxrwxrwt 6 root root 4096 5月 12 21:04 . drwxr-xr-x 4 root root 4096 5月 6 17:57 .. drwxr-xr-x 2 root root 4096 5月 6 18:29 guest drwxr-xr-x 2 root root 4096 5月 12 21:04 httpd drwxr-xr-x 2 root root 4096 5月 7 15:37 nitta drwxr-xr-x 2 root root 4096 5月 11 18:32 sshd $ ls -l /home/docker 合計 16 drwxr-xr-x 2 root root 4096 5月 6 18:29 guest drwxr-xr-x 2 root root 4096 5月 12 21:04 httpd drwxr-xr-x 2 root root 4096 5月 7 15:37 nitta drwxr-xr-x 2 root root 4096 5月 11 18:32 sshd
$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 145304f90056 ubuntu24_sshd_httpd "/entrypoint.sh" ... 0.0.0.0:11022->22/tcp, ubuntu24-httpd 0.0.0.0:11080->80/tcp, 0.0.0.0:11443->443/tcp, ...
$ docker attach ubuntu24-httpd ← docker attach コマンドで動作中のContainerに接続する# ← Container内の対話環境と再びつながった- (Container 内の root 権限で) www ユーザに login する。
# login www ← www ユーザにログインする Password: ← パスワードを入力する。エコーバックされない。Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.11.0-25-generic x86_64) ... To run a command as administrator (user "root"), use "sudo". See "man sudo_root" for details. www $ - (Container 内の www 権限で) パスワードを変更する。
www $ passwd Changing password for guest. Current password: パスワード ← エコーバックされない New password: 新しいパスワード ← エコーバックされない Retype new password: 新しパスワード ← エコーバックされない passwd: password updated successfully- Container 内の www ユーザ権限の対話環境を終了 Container 内の root 権限の対話環境に戻る。
$ exit logout$- Container 内の対話環境で Control-P + Control+Q をタイプすると、ゲストOSの対話環境は動作したままだが、手元の端末はホストOS の対話環境に戻る。
# ^P ^Q read escape sequence$- ssh を使ってネットワーク経由で Container の(新しい)対話環境にアクセスする。
$ ssh -p 11022 www@localhost The authenticity of host '[localhost]:11022 ([127.0.0.1]:11022)' can't be established. ED25519 key fingerprint is SHA256:qFfoWarJPGj1PdGzxmoI32TAs06byIOBrrewHN/5GCE. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '[localhost]:11022' (ED25519) to the list of known hosts. www@localhost's password: ← www のパスワードを入力する。エコーバックされない。Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.11.0-25-generic x86_64) ← Container 内の www 権限の対話環境にネットワーク経由でアクセスする * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro This system has been minimized by removing packages and content that are not required on a system that users do not log into. To restore this content, you can run the 'unminimize' command. To run a command as administrator (user "root"), use "sudo". See "man sudo_root" for details. www $ - (Container 内の www 権限の対話環境で) ユーザ名を確認する。
www $ whoami www- (Container 内の www 権限の対話環境で) ホームディレクトリを確認する。
www $ pwd /home/www- (Container 内の www 権限の対話環境で) ホームディレクトリのファイルを確認する。
www $ ls -a . .. .bash_history .bash_logout .bashrc .cache .profile- (Container 内の www 権限の対話環境で) 対話環境を終了する。
www $ exit ← Container の www 権限の対話環境を終了する logout Connection to localhost closed.$ &arr; ホストOS の対話環境に戻る- (ホスト OS の対話環境で) ホスト OS のファイアウォールの状態を確認する。
$ sudo ufw status 状態: アクティブ To Action From -- ------ ---- 80 ALLOW Anywhere 22 ALLOW Anywhere 443 ALLOW Anywhere 3389 ALLOW Anywhere 10022 ALLOW Anywhere- (ホスト OS の対話環境で) Container にポートフォワーディングする 11022 番, 11080 番, 11443 番 ポートを開ける。
- IPv4 と IPv6 の両方のポートを開放する場合
$ sudo ufw allow 11022 $ sudo ufw allow 11080 $ sudo ufw allow 11443- IPv4 の TCP のポートだけを開放する場合(推奨)
$ sudo ufw allow from 0.0.0.0/0 to any port 11022 proto tcp $ sudo ufw allow from 0.0.0.0/0 to any port 11080 proto tcp $ sudo ufw allow from 0.0.0.0/0 to any port 11443 proto tcp- (ホスト OS の対話環境で) ファイアウォールの状態を確認する。 外部から特定のポートへのアクセスが追加された。
- IPv4 と IPv6 の両方のポートを開放する場合
$ sudo ufw status ... To Action From -- ------ ---- 11022 ALLOW Anywhere 11080 ALLOW Anywhere 11443 ALLOW Anywhere ... 11022 (v6) ALLOW Anywhere (v6) 11080 (v6) ALLOW Anywhere (v6) 11443 (v6) ALLOW Anywhere (v6)- IPv4 の TCP のポートだけを開放する場合(推奨)
$ sudo ufw status To Action From -- ------ ---- ... 11022/tcp ALLOW Anywhere 11080/tcp ALLOW Anywhere 11443/tcp ALLOW Anywhere- [SSH] 他のPCから、「ホストOSのIPアドレス」とポートフォワーディングされるポート番号を指定してssh アクセスする。 ホストOSの 11022 番ポートにアクセスすると、Container の 22 番ポートにポートフォワーディングされる。
$ ssh -p 11022 www@192.168.12.3 ← ホストOSのIPアドレスと、ポートフォワーディングされるポート番号 www@192.168.12.3's password:Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.11.0-25-generic x86_64) ← Container の www 権限の対話環境が始まる * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro This system has been minimized by removing packages and content that are not required on a system that users do not log into. To restore this content, you can run the 'unminimize' command. Last login: Mon May 12 12:28:50 2025 from 172.17.0.1 To run a command as administrator (user "root"), use "sudo". See "man sudo_root" for details. $ whoami www $ pwd /home/www $ ls -a . .. .bash_history .bash_logout .bashrc .cache .profile $ exit ← Container の www 権限の対話環境を終了する logout Connection to 192.168.12.3 closed. $ ← 他の PC の対話環境に戻る- [WWW] 他のPC からブラウザを用いて、「ホストOSのIPアドレス」とポートフォワーディングされるポート番号を指定して WWW アクセスする。
URL: http://ホストOSのIPアドレス:ポート番号/
URL: http://192.168.12.3:11080/
- apache2 の再起動には supervisorctl を用いる。
$ supervisorctl restart apache2![]()
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-sshd-httpd 上のwwwサーバにアクセスする。
url は http://ホストosのipアドレス:11080/- container ubuntu24-sshd-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アドレス:11080/" ... 172.17.0.1 - - [04/may/2025:05:10:53 +0000] "get /work3/ http/1.1" 200 21202 "http://ホストosのipアドレス:11080/" ...- まず、aptのデータベースを更新する。
ネットワークコマンドをインストールする。← 今回は Dockerfile 内の RUN 文で install 済み。$ sudo apt updateifconfig, netstat, arp をインストールする$ sudo apt install -y net-toolstraceroute をインストールする$ sudo apt install -y iputils-tracepath tracerouteping をインストールする$ sudo apt install -y iputils-pingcurl をインストールする$ sudo apt install -y curlip をインストールする$ sudo apt install -y iproute2netstat
コマンドを用いて、ルーティング情報を調べる。 → 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 eth0ifconfig
でcontainer のipアドレスを調べる。 → 172.17.0.2 であることがわかる。$ ifconfig eth0: flags=4163mtu 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 対策
対策は3通りあるようだ。
- container を --net=host モードで起動する(ホストosがlinuxで、docker engine の場合に限る) 。 このとき、
-p
で指定した port forwarding 機能は無視される。- reverse proxy (nginxなど) をホストosで動かして、aapche コンテナに x-forwarded-for で情報を渡す。
- macvlan ネットワークで仮想的にホストと独立した ip アドレスを与える。
docker コンテナにホストとは別の ip を割り当て、lan 上のデバイスとして振る舞わせる。
docker network を生成する
network.php
「アクセスしてきたクライアントの正しいipアドレスが container 上の httpdサーバ (apache2) に伝わる」ように macvlan を使って「Container に物理 NIC と同じネットワークの独立した IP アドレスを与える」方法を採る。
前提条件と環境
- ホストOSのネットワーク: 192.168.12.0/24
- ホストOSのネットワークのゲートウェイ: 192.168.12.1
- 物理 NIC インタフェース名: eno01
Intel のCPUを持つPCに Ubuntu 24.04LTS をインストールした場合は eno1 となる。 Raspberry PI (ARM64) に Ubuntu 24.04LTS をインストールした場合は eth0 となる。 ifconfig コマンドで調べること。
- ホストOSのIPアドレス: 192.168.12.3
- Containerに割り当てるIPアドレス: 192.168.12.192/28 [192-207]
- ホストOSの接続しているネットワークを調べる。
- ネットワークアドレス: → 192.168.12.0/24
- ゲートウェイ: 192.168.12.1
- 物理NICインタフェース: eno1
$ netstat -nr カーネルIP経路テーブル 受信先サイト ゲートウェイ ネットマスク フラグ MSS Window irtt インタフェース 0.0.0.0 192.168.12.1 0.0.0.0 UG 0 0 0 eno1 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0 192.168.12.0 0.0.0.0 255.255.255.0 U 0 0 0 eno1- ホストOSの IP アドレスを調べる。
- ホストOSのIPアドレス: 192.168.12.3
$ ifconfig ... eno1: flags=4163mtu 1500 inet 192.168.12.3 netmask 255.255.255.0 broadcast 192.168.12.255 inet6 2409:11:3920:6400:5a47:caff:fe71:3b7d prefixlen 64 scopeid 0x0 inet6 2409:11:3920:6400:4c1a:ff8c:eab1:41c9 prefixlen 64 scopeid 0x0 inet6 fe80::5a47:caff:fe71:3b7d prefixlen 64 scopeid 0x20 ether 58:47:ca:71:3b:7d txqueuelen 1000 (イーサネット) ... - macvlan ネットワークを作成する。
$ docker network create -d macvlan \ --subnet=192.168.12.0/24 \ --gateway=192.168.12.1 \ -o parent=eno1 \ --ip-range=192.168.12.192/28 \ macvlan_net- docker のネットワーク一覧を表示する。macvlan_net が作成されていることがわかる。
$ docker network ls NETWORK ID NAME DRIVER SCOPE ebbd998b2086 bridge bridge local 17420af9f271 host host local 557533733a33 macvlan_net macvlan local a3538f29efc6 none null local$ docker network ls --no-trunc NETWORK ID NAME DRIVER SCOPE ebbd998b20868aea17c1e9f3cd85edb3c7c0ce9181edfe9b308284604275e136 bridge bridge local 17420af9f27199ef5081c56e85910d913c73ae8f3885e48e4ed0b09a06d48016 host host local 557533733a33e84ca9eb665736f6a273414778f30a3e744411596008728b0b2b macvlan_net macvlan local a3538f29efc60166d3f639d42894eff9f902649036619190011c3a66b262a06a none null local
Docker Contaner を生成する (2)
Image ubuntu24_sshd_httpd を用いて、 macvlan_net ネットワークに接続する、 新しい Container ubuntu24-sshd-httpd2 を生成する。
上記の「Docker Contaner を生成する (1)」に対して、以下の変更を加える。
- Container の起動オプションに
--network macvlan_net
オプションを追加することにより、 この Container はホストOSのネットワークを共有する。- Container の起動オプションで
-p
オプションは指定しない。 ホストOSのネットワークを共有した場合、port forwarding はできないため。- Conatiner のIPアドレスを -ip オプションで指定する。
- Conatiner が接続するネットワークを --network (ネットワーク名) で指定する。
Container を作成+実行する
- image から container を生成して起動する。 下の実行例はユーザ名を www とした場合である。
$ docker run --name ubuntu24-sshd-httpd-vlan --restart always \ -e UNAME=www -e UID=2000 -e GID=2000 \ --network macvlan_net \ --ip 192.168.12.193 \ --cap-add=NET_ADMIN \ -v /home/docker/httpd:/mnt/hostos \ -it ubuntu24_sshd_httpd起動オプション
- --name: 生成するcontainer の名前は ubuntu24-sshd-httpd
- --restart always: docker が起動すると、このコンテナも自動起動する。
- --network macvlan_net : Container は macvlan_net にアクセスする。
- --ip IPv4 アドレス: Container の IP アドレスを指定する。
- --cap-add=NET_ADMIN: ネットワークに関する特権をこの Container に与える。(セキュリティ上の問題になる可能性あり)
- -e: run 時に実行されるシェルスクリプト (entrypoint.sh) 中の環境変数を設定する。
環境変数名 値 UNAME www UID 2000 GID 2000 - -v: ホストOSの /home/docker/www が Container の/home/www/doc にマウントされる。
マウントポイント ホストOS ゲストOS /home/docker/www /home/www/doc - 使用する Docker Image は ubuntu24_sshd_httpd
- Container を起動した対話環境が、そのままContainer 内で動作する bash との対話環境になる。root権限でloginした状態である。
First run. Setting up ... Creating group www with GID=2000 Creating user www with UID=2000, GID=2000 info: Adding user `www' to group `sudo' ... ownership of '/home/www' retained as www:www No command provided. Starting bash ... root@961393dcc800:/# 2025-05-18 07:08:19,525 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-18 07:08:19,527 INFO supervisord started with pid 40 2025-05-18 07:08:20,529 INFO spawned: 'apache2' with pid 43 2025-05-18 07:08:20,531 INFO spawned: 'php-fpm' with pid 44 2025-05-18 07:08:20,533 INFO spawned: 'sshd' with pid 45 2025-05-18 07:08:21,568 INFO success: apache2 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2025-05-18 07:08:21,569 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2025-05-18 07:08:21,569 INFO success: sshd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) # ← Container 内の対話環境 (root 権限の bash) が動く- ネットワークコマンドはインストール済みである。もしも、インストールされていない場合は以下の手順でインストールする。
まず、aptのデータベースを更新する。# apt updateifconfig, netstat, arp をインストールする# apt install -y net-toolstraceroute をインストールする$ apt install -y iputils-tracepath tracerouteping をインストールする$ sudo apt install -y iputils-pingcurl をインストールする$ sudo apt install -y curlip をインストールする$ sudo apt install -y iproute2netstat
コマンドを用いて、ルーティング情報を調べる。 → Container が接続しているネットワークは 192.168.12.0/24で、 デフォルトのルーティング先が 192.168.12.1 であることがわかる$ netstat -nr Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 0.0.0.0 192.168.12.1 0.0.0.0 UG 0 0 0 eth0 192.168.12.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0ifconfig
でContainer のIPアドレスを調べる。 → 192.168.12.193 であることがわかる。$ ifconfig eth0: flags=4163mtu 1500 inet 192.168.12.193 netmask 255.255.255.0 broadcast 192.168.12.255 ether 8a:9e:8a:00:aa:16 txqueuelen 0 (Ethernet) RX packets 5434 bytes 30400112 (30.4 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 4498 bytes 300984 (300.9 KB) 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 8 bytes 1058 (1.0 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8 bytes 1058 (1.0 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 - Container では firewall は動作していない。現在の Image 元にした ubuntu:24.04 では ufw や iptavbles がインストールされていないため。
# iptables -L bash: iptables: command not found # ufw status bash: ufw: command not found- 手動で firewall を設定する。
ufw をインストールする。# apt update && apt install -y ufwufw を有効化する# ufw enable Status: active# ufw allow from 0.0.0.0/0 to any port 22 proto tcp Rule added # ufw allow from 0.0.0.0/0 to any port 80 proto tcp Rule added # ufw allow from 0.0.0.0/0 to any port 443 proto tcp Rule added外部からのアクセスはデフォルトで禁止にする。# ufw default deny incomingファイアウォールの設定状況を見る# ufw status Status: active To Action From -- ------ ---- 22/tcp ALLOW Anywhere 80/tcp ALLOW Anywhere 443/tcp ALLOW Anywhere- ネットワーク上の他のマシンから、ssh接続できることを確認する。
sshで$ ssh www@192.168.12.193[注意] パスワードを迅速に変更しておくこと。- ネットワーク上の他のマシンから httpd 接続できることを確認する。
ブラウザで url: http://192.168.12.193/
macvlan に関する注意
- -cap-add=NET_ADMIN オプションを指定せずに起動したContainer 内の root 権限で ufw を実行すると、エラーとなる。
$ sudo ufw status ... WARN: initcaps [Errno 2] iptables v1.8.10 (nf_tables): Could not fetch rule set generation id: Permission denied (you must be root) Rules updated原因
Docker は通常、CAP_NET_ADMIN などの 特権ケーパビリティを制限している。 そのため、Container で ufw を使う場合、通常の root 権限では不十分なことが多い。対策
方法1: --cap-add=NET_ADMIN を付けて起動するdocker run \ --cap-add=NET_ADMIN \ --network macvlan_net \ --ip 192.168.1.100 \ -it ubuntu:24.04方法2: コンテナを「特権モード」で起動する(セキュリティ上のリスクがあるため、推奨されない)docker run \ --privileged \ --network macvlan_net \ --cap-add=NET_ADMIN \ --ip 192.168.1.100 \ -it ubuntu:24.04- (参考) Dockerfile に firewall 設定を含む手順
(注意) "ufw enable" はインタラクティブな挙動をするため、適切な処理が必要となる。
Dockerfileに追加 FROM ubuntu:24.04 RUN apt update && apt install -y ufw RUN ufw allow 80 && ufw enable代替案(推奨)
ufw を使わず Apache2 などのアプリ側でバインドポートを限定する。例:Apache2 を 80 のみで Listen
![]()