海外VPSにDockerを入れる
Dockerを入れること自体は5分で終わります。海外VPSで問題になるのはそのあとで、ファイアウォールを設定したのにコンテナのポートが全世界に開いている、という事故が最も多いです。
当サイトは各VPS事業者のアフィリエイトプログラムに参加しており、リンク経由でのお申し込みにより報酬を受け取る場合があります。ただし掲載順位・評価・実測データは編集方針と計測結果のみに基づいており、報酬額による優遇は一切行いません。日本リージョンが無い事業者や、報酬が発生しない事業者も同じ基準で掲載しています。
先に結論
- 導入は公式リポジトリから入れる。ディストリ標準の
docker.ioは古い - UFWで塞いだポートはDockerに貫通される。 これが最大の落とし穴
- 公開が不要なポートは
127.0.0.1にバインドする。それだけで大半の事故が消える - 1GBプランはビルドで落ちる。スワップを用意するか4GB以上を選ぶ
1. インストールする
Ubuntu 22.04 / 24.04 での手順です。Docker公式のaptリポジトリを使います。
# 古いパッケージが入っていれば外す
sudo apt remove -y docker docker-engine docker.io containerd runc
# リポジトリを使うための前提パッケージ
sudo apt update
sudo apt install -y ca-certificates curl
# 公式のGPG鍵を置く
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# リポジトリを登録する
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 本体を入れる
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
動作確認します。
sudo docker run --rm hello-world
sudoなしで実行できるようにする
sudo usermod -aG docker $USER
一度ログアウトして入り直すと反映されます。
2. UFWがDockerに貫通される問題
ここが海外VPSで最も事故が多いところです。
セキュリティ設定のとおりUFWを設定し、SSH以外を塞いだつもりでも、Dockerで公開したポートはUFWを無視して外部から到達します。
何が起きるか
# 8080番を明示的に塞ぐ
sudo ufw deny 8080
# それでもコンテナを公開すると……
docker run -d -p 8080:80 nginx
この状態で外部から http://<サーバーのIP>:8080/ を叩くと、繋がります。 UFWの状態を見ても 8080 DENY と表示されたままです。
なぜそうなるのか
UFWは iptables の INPUT チェーンにルールを書きます。一方Dockerは、ポート公開を実現するために nat テーブルの PREROUTING にDNAT(宛先変換)ルールを書き込みます。
パケットの処理順序では DNAT のほうが先に評価されるため、UFWの INPUT ルールに到達する前に転送が成立します。設定ミスではなく、両者の仕組みがそういう順序になっているというだけです。
対処1:公開しない(推奨)
いちばん確実なのは、そもそも外に出さないことです。バインド先を明示します。
# 悪い例:全インターフェースに公開される
docker run -d -p 8080:80 nginx
# 良い例:ホスト内部からしか見えない
docker run -d -p 127.0.0.1:8080:80 nginx
Compose なら次のように書きます。
services:
web:
image: nginx:alpine
ports:
- "127.0.0.1:8080:80"
Tailscale などのプライベートネットワーク越しに使いたい場合は、そのインターフェースのIPを指定します。
ports:
- "100.x.x.x:8080:80" # Tailscale のIPだけに公開
外部公開が必要なものは、リバースプロキシを1つだけ立ててそこに集約してください。 公開ポートが80/443の2つだけになれば、管理対象が減って事故も減ります。
対処2:DOCKER-USERチェーンに書く
どうしても公開ポートを持ったまま制御したい場合は、Dockerが用意している DOCKER-USER チェーンを使います。ここはDockerのルールより先に評価され、Dockerに消されません。
# 特定のIPからのみ 8080 を許可し、それ以外は落とす
sudo iptables -I DOCKER-USER -p tcp --dport 8080 ! -s 203.0.113.10 -j DROP
今の状態を確認する
自分のサーバーが外に何を晒しているかは、これで見えます。
# LISTENしているポートと、そのバインド先
sudo ss -tlnp
0.0.0.0:8080 や :::8080 と出ていれば全世界に公開されています。127.0.0.1:8080 なら外からは見えません。
Dockerが入れたルールそのものを見るならこちらです。
sudo iptables -t nat -L DOCKER -n
sudo iptables -L DOCKER-USER -n
DOCKER-USER が空(ポリシーRETURNのみ)なら、公開ポートに対する制限は何もかかっていません。
3. メモリとスワップ
海外格安VPSは小さいプランほどスワップが設定されていないことが多く、docker build の途中でOOM Killerに落とされる事故が起きます。
| メモリ | 実際のところ |
|---|---|
| 512MB | 実用外。デーモンだけで数十MB食う |
| 1GB | 動くが、ビルドで落ちやすい。スワップ必須 |
| 2GB | 軽いコンテナを数個なら |
| 4GB | 一般的な用途の下限。ここから安心して使える |
| 8GB以上 | 複数スタック、DB込みの構成 |
スワップを作ります。
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 再起動後も有効にする
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
4. ディスクを食い潰さない
Dockerは使っていないイメージ・停止済みコンテナ・ビルドキャッシュを溜め込みます。25GBのプランだと、数ヶ月でディスクフルになることがあります。
# 何にどれだけ使っているか
docker system df
# 停止コンテナ・未使用イメージ・ビルドキャッシュを消す
docker system prune -a
ディスクI/Oが速いほどビルドもpullも快適です。当サイトの計測ノード(Contabo東京)で実測したところ、ランダム読み4Kで約30,000 IOPS、連続読みで約960MB/s でした。詳細は実測データにまとめています。
5. ARM(aarch64)のVPSでの注意
Oracle Cloudの無料枠(Always Free / ARM 4コア・24GB)や一部の格安プランは arm64 です。x86_64ではありません。
公式イメージ(nginx、postgres、redis 等)はarm64版が用意されているので普通に動きます。問題は個人や小規模プロジェクトが公開しているイメージで、amd64しか無いことがあります。
exec /entrypoint.sh: exec format error
このエラーが出たら、アーキテクチャの不一致です。事前に確認できます。
docker manifest inspect <イメージ名>:<タグ> | grep architecture
6. どのVPSを選ぶか
Dockerを本気で使うなら、効いてくるのはメモリとディスク容量です。CPUのコア数よりそちらが先に足りなくなります。
| 使い方 | 目安 | 相性のよい選択 |
|---|---|---|
| コンテナ1〜2個の検証 | 2GB | 時間課金で捨てやすいVultr |
| 常用(アプリ+DB) | 4〜8GB | 単価で選ぶならContabo |
| 複数スタックを常駐 | 16GB〜 | Contabo、または無料枠のOracle(在庫次第) |
日本リージョンの有無で変わるのは通信のレイテンシだけで、ビルド速度には効きません。ただしイメージのpullは近いほうが速いので、日本リージョンがある会社のほうが体感は良くなります。日本リージョンを持つ会社はこちらにまとめています。
PR
Dockerを常駐させるならスペック単価で選ぶ
東京リージョンがあり、4vCPU/8GBが月5ユーロ前後。コンテナを複数常駐させる用途ではメモリとディスクが先に足りなくなるので、この価格帯で8GB載るのは効きます。時間課金は無いため、短期の検証用途にはVultrのほうが向きます。
- 日本リージョン: 東京
- 最安 €4.99〜 / 月単位(時間課金なし)
- スペック単価が圧倒的。8GB RAMが€4.99から
上記は広告リンクです。価格・特典は公式サイトの表示が最新です。
よくある質問
UFWを有効にしているのにDockerのポートが外から見えるのはなぜですか
Dockerが公開ポートの転送をiptablesのnatテーブル(PREROUTING)に直接書き込むためです。UFWのルールはINPUTチェーンで評価されますが、DNATはその手前で処理されるため、UFWのdenyが評価される前に転送が成立します。設定ミスではなく仕様です。対処はポートを127.0.0.1にバインドするか、DOCKER-USERチェーンにルールを書くかの2択です。
対処としてどちらを選ぶべきですか
127.0.0.1へのバインドを推奨します。-p 8080:80 ではなく -p 127.0.0.1:8080:80 と書くだけで、そもそも外部に出なくなります。外部公開が必要なものはリバースプロキシ(nginx等)を1つだけ公開し、その1ポートをUFWで管理するのが最も事故が少ない構成です。
メモリ1GBのプランでDockerは動きますか
動きますが、イメージのビルド中にOOM Killerで落ちることがよくあります。実行するだけなら1GBでも足りることが多い一方、ビルドは瞬間的にメモリを食います。スワップを2GB作っておくと大半は回避できます。常用するなら4GB以上を選んでください。
Oracle Cloudの無料ARM枠でDockerは使えますか
使えますが、CPUアーキテクチャがarm64(aarch64)である点に注意が必要です。公式イメージの多くはarm64に対応していますが、個人が公開しているイメージはamd64のみのことがあり、その場合 exec format error で起動しません。docker manifest inspect でタグの対応アーキテクチャを事前に確認してください。