既存のDockerコンテナーにポートマッピングを割り当てるにはどうすればよいですか?


436

ここで何かを誤解したかどうかはわかりませんが、イメージから新しいコンテナを作成することによってのみポートマッピングを設定できるように思われます。既存のDockerコンテナーにポートマッピングを割り当てる方法はありますか?


3
iptablesを使用すると、
Choldrim

2
これは仕様によるものだと思います。Dockerはあなたを「繰り返し可能」にしようと試みており、コンテナーは一種の「記録システム」です。コンテナーに影響を与えないステップとして行うことは、簡単に失われる手動のステップになります。別の言い方をすると、コンテナーは、操作に必要なすべての構成を表す必要があります。したがって、新しいポートを開きたい場合は、新しいコンテナを作成する必要があります。
ランスの種類

2
古い質問と私はそれに答えていませんが、おそらくあなたとこの質問と答えを支持する人々は、Dockerの概念を完全に誤解しているかもしれないと言いたいです。Dockerはステートレスアプリケーション用であり、何度もスケールアップまたはスケールダウンできます。再作成できない本番環境のコンテナ内で何かを永続化しないでください。永続化する必要がある場合は、ディレクトリをマップしてください。Dockerは「light vm」のようなものではありません。探しているのはlinuxcontainers.orgでしょう。lxdはdockerコンセプトに基づいていますが、「light vm」を念頭に置いています。
Edgar Carvalho

これが役立つかもしれない場合に備えて、「Kitematic」ツールを使用して、すでに実行中のコンテナにポートマッピングを追加することが可能です。これは、まったく同じことを行うが、少しグーグルで行うには
docker

回答:


298

次の場所でhostconfig.jsonファイルを直接編集して、ポートマッピングを変更できます。 /var/lib/docker/containers/[hash_of_the_container]/hostconfig.json

[hash_of_the_container]はdocker inspect <container_name>コマンドを使用して決定でき、「Id」フィールドの値はハッシュです。

1) stop the container 
2) stop docker service (per Tacsiazuma's comment)
3) change the file
4) restart your docker engine (to flush/clear config caches)
5) start the container

したがって、このアプローチでイメージを作成する必要はありません。ここで再起動フラグを変更することもできます。

PS ホストマシンごとにドッカーエンジンを正しく再起動する方法については、https://docs.docker.com/engine/admin/にアクセスしてください。私は使用sudo systemctl restart dockerのUbuntu 16.04上で実行されている私のドッカエンジンを再起動します


17
dockerが停止すると、変更が上書きされたように見えるため、
2。dockerを

5
私は上記を試してみましたが、うまくいきました。詳細については、mybrainimage.wordpress.com
2017/02/05

11
コンテナーを停止し、Dockerエンジンを停止して、両方hostconfig.jsonを変更config.v2.jsonし、これを機能させることが重要です。詳細を確認するには、@ rohitmohtaが提供するリンクを使用してください。
Kalpak Gadre 2017

5
MacでDockerアプリを使用している場合は1つだけ、私のために働いた、ここの指示に従って/ var / lib / docker / containersフォルダにアクセスします:stackoverflow.com/a/41226917/2048266、基本的に実行screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/ttyttyが実行されたら、次のことができます/ var / lib /
dockerに

14
Windowsの場合、誰でもconatinersフォルダの場所を教えてください。
Vijay

463

この問題にも興味があります。

以下のよう@Thasmoが述べたように、ポート転送はONLYで指定することができますdocker run(とdocker create)コマンド。
他のコマンドにdocker start-pオプションがなく、docker port現在の転送のみを表示します。

ポート転送を追加するには、常に次の手順に従います。

  1. コンテナの実行を停止する

    docker stop test01
    
  2. コンテナをコミットする

    docker commit test01 test02
    

    注:上記test02は、私がtest01コンテナから構築している新しいイメージです。

  3. コミットされたイメージから再実行

    docker run -p 8080:8080 -td test02
    

最初の8080はローカルポートで、2番目の8080はコンテナポートです。


14
test01の名前を保持したい場合はどうなりますか?
user69715 '25年

12
Dockerに未解決の問題があり、ポート指定(--publish)を許可するかどうかは誰でも知っていdocker startますか?
Elijah Lynn

8
そして、このシナリオのボリュームはどうなりますか?
Andrew Savinykh 2017年

78
これはひどい解決策です。250の賛成票を獲得できたかどうかはわかりません。たぶんどのようにして賛成票を投じた人たちは、このソリューションがどのような混乱を引き起こすのかを知りませんでした。はい、それはひどいです、そしてそれは別のポートで実行されている新しいコンテナーを開始することと同じです。
18年

25
@Arrrrおそらく、より良い答えを残したいですか?あなたがこれを行うためのより良い方法を私たちに言ってくれれば、私たちは皆感謝するでしょう。
crockeea 2018年

40

「存在する」が「実行中」を意味する場合、(現在のところ)ポートマッピングを追加することはできません。

ただし、サービスを停止/再起動せずに実行中のコンテナで公開する必要がある場合は、パイプラインなどを使用して新しいネットワークインターフェースを動的に追加できます。


4
これが一番の答えです。簡潔であり、それは他の誰もしないOPの質問に対処します! 時には否定的な結果が結果です!
曇りのち

19

実行中のコンテナーにポートマッピングを適用できるかどうかは不明です。新しいコンテナーの作成とは異なるコンテナーの実行中にポート転送を適用できます。

$ docker run -p <public_port>:<private_port> -d <image>  

コンテナの実行を開始します。このチュートリアルでは、ポートのリダイレクトについて説明します。


2
そう、コンテナーの作成時にポートマッピングなどのオプションを設定することしかできないようです。
thasmo 2013年

20
ちなみに、この答えは完全に正しいわけではありません。docker run新しいコンテナを作成して開始します。これは、doのdocker create後にを続けた場合と同じdocker startです。
Trevor Sullivan、

19

hostconfig.jsonの編集が機能していないようです。そのポートが公開されていてホストに公開されていないだけです。コンテナをコミットして再作成することは、私にとって最善の方法ではありません。誰も言及していませんdocker networkか?

最善の解決策は、同じネットワーク内でリバースプロキシを使用することです。

  1. 以前のコンテナが名前付きコンテナにない場合は、新しいネットワークを作成します。

    docker network create my_network

  2. 作成したネットワークに既存のコンテナーを結合します

    docker network connect my_network my_existing_container

  3. 同じネットワークに参加して、必要なポートを公開するリバースプロキシサービス(nginxなど)を開始します

    docker run -d --name nginx --network my_network -p 9000:9000 nginx

    オプションでnginx のdefault.confを削除します

    docker exec nginx rm /etc/nginx/conf.d/default.conf

  4. 新しいnginx構成を作成する

    server
    {
        listen 9000;
    
        location / {
            proxy_pass http://my_existing_container:9000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
    

    設定をnginxコンテナにコピーします。

    docker cp ./my_conf.conf nginx:/etc/nginx/conf.d/my_conf.conf

  5. nginxを再起動します

    docker restart nginx

利点:新しいポートを公開するために、ビジネスコンテナーに触れることなく、必要に応じてnginxコンテナーを安全に停止/更新/再作成できます。nginxのゼロダウンタイムが必要な場合は、同じネットワークに参加するリバースプロキシサービスをさらに追加することができます。さらに、コンテナは複数のネットワークに参加できます。

編集:

非HTTPサービスをリバースプロキシするために、構成ファイルは少し異なります。以下に簡単な例を示します。

upstream my_service {
    server my_existing_container:9000;
}

server {
    listen 9000;
    proxy_pass my_service;
}

1
驚くほど実用的ですが、エンタープライズシステムでは、このアプローチは難読化されているようです。単一のシステムでワークフローを制御する方がはるかに優れています。
アフシン

1
@Afshinエンタープライズシステムまたはプロジェクトの場合、このソリューションは再作成(ダウンタイムの原因)またはhostconfig.jsonファイルのハッキング(少なくとも公式には導入されていません)よりも優れていると思います。追加のコンテナは、ビジネスコンテナに変更を加えるのではなく、内部ポートを公開するだけです。
Sean C.

1
素晴らしいアプローチ。コンテナーがプロキシーの背後で機能するようにnginxを別の方法で構成する必要がありましたが、正しい方法のようです。ブルーグリーンの展開でも機能します。
Brooks DuBois

17

藤本洋一の例test01はコンテナtest02ですが、画像です。

実行する前にdocker run、元のコンテナを削除してから、コンテナに同じ名前を再度割り当てることができます。

$ docker stop container01
$ docker commit container01 image01
$ docker rm container01
$ docker run -d -P --name container01 image01

-P手動で割り当てるのではなく、ポートをランダムなポートに公開するために使用します)。


12
ご留意ください。内部のアプリケーションに応じて、すべてのデータが失われます。
バリー

14

実行docker run <NAME>すると、新しいイメージが生成されますが、これはおそらく望んでいるものではありません。

現在の画像を変更したい場合は、以下を実行してください。

docker ps -a

ターゲットコンテナのIDを取得して、次の場所に移動します。

cd /var/lib/docker/containers/<conainerID><and then some:)>

コンテナを停止します。

docker stop <NAME>

ファイルを変更する

vi config.v2.json

"Config": {
    ....
    "ExposedPorts": {
        "80/tcp": {},
        "8888/tcp": {}
    },
    ....
},
"NetworkSettings": {
....
"Ports": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],

そしてファイルを変更する

vi hostconfig.json

"PortBindings": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],
     "8888/tcp": [
         {
             "HostIp": "",
             "HostPort": "8888"
         } 
     ]
 }

Dockerを再起動すると動作します。


2
これは、Dockerバージョン17.09.0-ceでは動作しませんでした。コンテナの設定を開始した後、上書きされて古い値に戻りました。
thegeko

3
ホストシステム@thegekoでdockerサービスを再起動します
yurenchen

1
これは機能します!tks!1.stopコンテナー、2.changeファイル、3.restart docker、4.start backコンテナー
datdinhquoc

12

逆に、Dockerの深度構成に慣れていない場合は、IPtablesが役に立ちます。

iptables -t nat -A DOCKER -p tcp --dport ${YOURPORT} -j DNAT --to-destination ${CONTAINERIP}:${YOURPORT}

iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source ${CONTAINERIP} --destination ${CONTAINERIP} --dport ${YOURPORT}

iptables -A DOCKER -j ACCEPT -p tcp --destination ${CONTAINERIP} --dport ${YOURPORT}

これはトリックであり、私のシナリオでこれが機能することをお勧めしません。コンテナーを停止できなかったため、同様に役立つことを願っています。


これは素晴らしい答えです!ありがとうございました!にマップDOCKER_PORTする場合MACHINE_PORT、どの部分を変更する必要がありますか?
CiprianTomoiagă、2018

dockerはこの手動の追加については知らないことに注意してください。ポートを適切に公開しているDockerを使用して後でサービスを再起動しても、SOエントリは削除されません。そのため、何かが変更された場合は、iptablesを注意深く確認してください。特に重複するエントリを探してください!
アンソニー

8

sshのような便利なツールを使用して、これを簡単に実現します。

私はubuntuホストとubuntuベースのDockerイメージを使用していました。

  1. docker内にopenssh-clientがインストールされています。
  2. 外部のDocker(ホスト)にはopenssh-serverサーバーがインストールされています。

新しいポートをマッピングする必要がある場合、

Docker内で次のコマンドを実行します

ssh -R8888:localhost:8888 <username>@172.17.0.1

172.17.0.1は、DockerインターフェイスのIPでした(ifconfig docker0 | grep "inet addr" | cut -f2 -d":" | cut -f1 -d" "ホストで実行することで取得でき ます)。

ここでは、ローカルの8888ポートをホストの8888にマッピングしました。必要に応じてポートを変更できます。

もう1つのポートが必要な場合は、sshを強制終了し、新しいポートを使用してそれに-Rの行を1つ追加できます。

これをnetcatでテストしました。


2
  1. Dockerエンジンとそのコンテナを停止します。
  2. /var/lib/docker/containers/${container_id}ディレクトリに移動して編集hostconfig.json
  3. PortBindings.HostPort変更する内容を編集します。
  4. Dockerエンジンとコンテナを起動します。

0

@ Fujimoto-Youichiの応答を補足するものとして

を使用$ docker run -P CONTAINER して、コンテナーの作成中にポートをランダムにマップすることもできますが、セキュリティascpectに注意してください!

-Peq to --publish-all: "すべての公開されたポートをランダムなポートに公開します"、

次にdocker inspect CONTAINER、以下の画像に示すように、ポートマッピングのフィンを実行します。

rabbitmqコンテナーのdocker inspectですべてのポートのマッピングを表示

詳細について読むdocker run -Pドッカラン


これは、既存のLIVEコンテナーにポートを追加するものではありません。
アンソニー

コメントの冒頭で述べたように、それは単なる追加です!! そして、コマンドの場合:提供されるdockerドキュメントリンクから:-publish-all、-P公開されたすべてのポートをランダムなポートに公開します
ans1genie

-1

WindowsおよびMacユーザーの場合、マッピングポートを変更する簡単で使いやすい方法がもう1つあります。

  1. kitematicをダウンロード

  2. コンテナーの設定ページに移動し、[ポート]タブで、公開されているポートを直接変更できます。

  3. コンテナをもう一度起動します


2
私はこのアプローチを試みました。キネマティックは確かにポートマッピングを適用しました。ただし、それらを適用するために、元のイメージからコンテナが再作成されました。したがって、コンテナ自体に加えられた変更が失われるのを恐れている場合は、このメソッドを使用しないでください。
VeganHunter 2018

1
私はこれを選択しました。質問には答えず、新しいコンテナーを作成します。しかし、少なくともそれは機能し、このSO結果は私の検索中に現れました。+1
2b77bee6-5445-4c77-b1eb-4df3e5

-7

短い回答:ポートマッピングを既存のDockerコンテナーに割り当てることはできません

新しいコンテナが必要です...それに対処してください。


4
態度の必要はありません。また、この答えは完全に詳細に欠けています。
lovefaithswing

1
詳細は必要ありません。口調は、この時間節約の答えとコンテナの一時的な性質を伝えるために重要です。
スティーブン

-11

実行中のコンテナーのポートを変更するだけの場合は、次のようにします。

  1. 既存のコンテナを停止する

    sudo docker stop NAME

  2. 新しいポートマッピングで再起動します

    sudo docker run -d -p 81:80 NAME

ここで:

「-d」を背景に/ Dockerをデーモン化

"-p"ポートマッピングを有効にする

ブラウザでアクセスするために使用する "81"外部(公開)ポート

「80」内部Dockerコンテナーの待機ポート


4
これは間違っています。docker runコマンドNAMEで一方からコンテナを実行するために画像の名前で停止するコンテナの名前を指します。docker stopNAME
ジョナタン

1
「docker run」は新しいコンテナを作成します。その名前のコンテナーは1つしか持てないため、停止したコンテナーと同じコンテナー名を使用することはできません。したがって、「docker stop NAME」、docker container rm NAME、次に「docker run -d -p 81:80 NAME」と入力する必要があります。
ランスの種類
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.