Làm cách nào để chỉ định ánh xạ cổng cho bộ chứa Docker hiện tại?


436

Tôi không chắc mình đã hiểu nhầm điều gì ở đây, nhưng có vẻ như chỉ có thể đặt ánh xạ cổng bằng cách tạo một thùng chứa mới từ một hình ảnh. Có cách nào để gán ánh xạ cổng cho bộ chứa Docker hiện tại không?


3
Sử dụng iptables có thể hoạt động như câu trả lời này Phơi bày một cổng trên Container Docker trực tiếp
Choldrim

2
Tôi nghi ngờ đây là do thiết kế. Docker đang cố gắng buộc bạn phải "lặp lại" và container là một loại "hệ thống hồ sơ". Bất cứ điều gì bạn làm như bước không ảnh hưởng đến container sẽ là bước thủ công dễ bị mất. Nói một cách khác: Bạn muốn container của bạn đại diện cho tất cả các cấu hình cần thiết để hoạt động. Vì vậy, nếu bạn muốn mở một cổng mới, thì bạn cần tạo một container mới.
Lance Kind

2
Câu hỏi cũ và tôi không trả lời nó, nhưng tôi muốn nói rằng có lẽ bạn và mọi người phản đối câu hỏi này và câu trả lời có thể đã hiểu sai hoàn toàn khái niệm về docker. Docker là cho ứng dụng phi trạng thái, có thể tăng hoặc giảm nhiều lần. Bạn không bao giờ nên duy trì một cái gì đó bên trong thùng chứa cho một môi trường sản xuất không thể được tạo lại, nếu bạn cần phải kiên trì, hãy ánh xạ các thư mục. Docker không phải là một cái gì đó giống như "light vm", có thể thứ bạn đang tìm kiếm là linuxcontainers.org, lxd dựa trên khái niệm docker nhưng trong tâm trí "light vm".
Edgar Carvalho

chỉ trong trường hợp điều này có thể giúp ích, có thể sử dụng công cụ "Kitical" để thêm ánh xạ cổng vào các container đã chạy. Điều này có nghĩa là phải có lệnh docker để thực hiện chính xác điều tương tự nhưng với một chút googling :) Chúc may mắn
Yaffah

Câu trả lời:


298

Bạn có thể thay đổi ánh xạ cổng bằng cách chỉnh sửa trực tiếp hostconfig.jsontệp tại /var/lib/docker/containers/[hash_of_the_container]/hostconfig.json

Bạn có thể xác định [hash_of_the_container] thông qua docker inspect <container_name>lệnh và giá trị của trường "Id" là hàm băm.

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

Vì vậy, bạn không cần phải tạo một hình ảnh với phương pháp này. Bạn cũng có thể thay đổi cờ khởi động lại ở đây.

PS Bạn có thể truy cập https://docs.docker.com/engine/admin/ để tìm hiểu cách khởi động lại chính xác công cụ docker của bạn theo máy chủ của bạn. Tôi đã sử dụng sudo systemctl restart dockerđể khởi động lại công cụ docker đang chạy trên Ubuntu 16.04


17
Khi docker dừng, nó dường như ghi đè lên các thay đổi của bạn, vì vậy 2. dừng docker, 3. thay đổi tập tin, 4. khởi động công cụ
docker

5
Tôi đã thử ở trên và nó hoạt động. Để biết thêm chi tiết, xem: mybrainimage.wordpress.com/2017/02/05/ Từ
rohitmohta

11
Điều quan trọng là dừng container, dừng động cơ docker và thay đổi cả hai hostconfig.jsonconfig.v2.jsonđể làm cho công việc này. Sử dụng liên kết được cung cấp bởi @rohitmohta để xem chi tiết.
Kalpak Gadre

5
làm việc cho tôi, chỉ một điều nếu sử dụng ứng dụng docker trên mac, hãy làm theo hướng dẫn tại đây để truy cập thư mục / var / lib / docker / container: stackoverflow.com/a/41226917/2048266 , về cơ bản là chạy screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/ttykhi bạn có thể chạy tty điều hướng đến / var / lib /
docker

14
Đối với các cửa sổ, có ai có thể chia sẻ cho tôi vị trí của thư mục conatiners không?
Vijay

463

Tôi cũng quan tâm đến vấn đề này.

Như @Thasmo đã đề cập, chuyển tiếp cổng có thể được chỉ định CHỈ với lệnh docker run(và docker create).
Các lệnh khác, docker startkhông có -ptùy chọn và docker portchỉ hiển thị chuyển tiếp hiện tại.

Để thêm chuyển tiếp cổng, tôi luôn làm theo các bước sau,

  1. dừng chạy container

    docker stop test01
    
  2. cam kết container

    docker commit test01 test02
    

    LƯU Ý: Trên đây, test02là một hình ảnh mới mà tôi đang xây dựng từ test01container.

  3. chạy lại từ hình ảnh được cam kết

    docker run -p 8080:8080 -td test02
    

Trong đó 8080 đầu tiên là cổng cục bộ và 8080 thứ hai là cổng container.


14
Nếu tôi muốn giữ tên test01 thì sao?
dùng69715

12
Bất cứ ai cũng biết nếu có một vấn đề mở với Docker để cho phép đặc tả cổng (--publish) với docker start?
Elijah Lynn

8
Và điều gì xảy ra với các tập trong kịch bản này?
Andrew Savinykh

78
Đây là một giải pháp khủng khiếp, tôi không biết làm thế nào nó kiếm được 250 lượt upvote. Có lẽ những người bị kích thích không biết loại giải pháp này gây ra sự lộn xộn. Vâng, điều đó thật tồi tệ, và nó tương đương với việc bắt đầu một container mới chạy trên một cổng khác.
Arrrr

25
@Arrrr Có lẽ bạn muốn để lại một câu trả lời tốt hơn? Tôi chắc rằng tất cả chúng ta sẽ đánh giá cao nếu bạn nói với chúng tôi cách tốt hơn để làm điều này.
crockeea

40

Nếu "hiện tại" bạn có nghĩa là "đang chạy", thì hiện tại không thể (hiện tại) có thể thêm ánh xạ cổng.

Tuy nhiên, bạn có thể tự động thêm giao diện mạng mới, ví dụ như Pipework , nếu bạn cần để lộ một dịch vụ trong một container đang chạy mà không dừng / khởi động lại nó.


4
Đây phải là câu trả lời hàng đầu. Cô đọng và nó giải quyết câu hỏi của OP mà không ai khác làm được! Đôi khi một kết quả tiêu cực là một kết quả!
Một phần mây

19

Không chắc chắn nếu bạn có thể áp dụng ánh xạ cổng một container đang chạy. Bạn có thể áp dụng chuyển tiếp cổng trong khi chạy một container khác với việc tạo một container mới.

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

sẽ bắt đầu chạy container. Hướng dẫn này giải thích chuyển hướng cổng.


2
Vì vậy, có vẻ như chỉ có thể đặt các tùy chọn như ánh xạ cổng khi tạo vùng chứa.
thasmo

20
FYI câu trả lời này không hoàn toàn chính xác. docker runtạo và bắt đầu một container mới. Nó tương đương với việc làm docker createtheo sau docker start.
Trevor Sullivan

19

Chỉnh sửa hostconfig.json dường như không hoạt động. Nó chỉ kết thúc với cổng đó được tiếp xúc nhưng không được công bố để lưu trữ. Cam kết và tái tạo container không phải là cách tiếp cận tốt nhất với tôi. Không ai nhắc đến docker network?

Giải pháp tốt nhất sẽ là sử dụng proxy đảo ngược trong cùng một mạng

  1. Tạo một mạng mới nếu vùng chứa trước của bạn không nằm trong bất kỳ mạng nào được đặt tên.

    docker network create my_network

  2. Tham gia container hiện tại của bạn vào mạng đã tạo

    docker network connect my_network my_existing_container

  3. Bắt đầu dịch vụ proxy đảo ngược (ví dụ nginx) xuất bản các cổng bạn cần, tham gia cùng một mạng

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

    Tùy chọn xóa default.conf trong nginx

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

  4. Tạo cấu hình nginx mới

    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;
        }
    }
    

    Sao chép cấu hình vào nginx container.

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

  5. Khởi động lại nginx

    docker restart nginx

Ưu điểm : Để xuất bản các cổng mới, bạn có thể dừng / cập nhật / tạo lại container nginx một cách an toàn mà bạn muốn mà không cần chạm vào vùng chứa doanh nghiệp. Nếu bạn cần thời gian xuống 0 cho nginx, có thể thêm nhiều dịch vụ proxy đảo ngược tham gia vào cùng một mạng. Ngoài ra, một container có thể tham gia nhiều hơn một mạng.

Biên tập:

Để đảo ngược dịch vụ proxy không phải http, tệp cấu hình hơi khác một chút. Đây là một ví dụ đơn giản:

upstream my_service {
    server my_existing_container:9000;
}

server {
    listen 9000;
    proxy_pass my_service;
}

1
Thật tuyệt vời và thiết thực, nhưng đối với các hệ thống doanh nghiệp, cách tiếp cận này dường như đang gây khó chịu. Sẽ tốt hơn nhiều nếu để một hệ thống duy nhất kiểm soát quy trình làm việc.
Afshin

1
@Afshin Tốt cho các hệ thống hoặc dự án doanh nghiệp, tôi nghĩ giải pháp này tốt hơn so với việc tạo lại (gây mất thời gian) hoặc hack tệp hostconfig.json (ít nhất là không được giới thiệu chính thức). Container bổ sung chỉ hiển thị cổng nội bộ của doanh nghiệp của bạn, thay vì thực hiện bất kỳ thay đổi nào đối với cổng đó.
Sean C.

1
Cách tiếp cận tuyệt vời. Tôi cần phải cấu hình nginx khác nhau để container của tôi hoạt động phía sau proxy, nhưng có vẻ như là cách chính xác để thực hiện. Hoạt động cho triển khai xanh-xanh quá.
Brooks DuBois

17

Trong ví dụ của Fujimoto Youichi test01là một container, trong khi đó test02là một hình ảnh.

Trước khi làm, docker runbạn có thể loại bỏ container ban đầu và sau đó gán lại container cùng tên:

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

(Sử dụng -Pđể hiển thị các cổng thành các cổng ngẫu nhiên thay vì gán thủ công).


12
Xin hãy lưu ý. bạn sẽ MẤT tất cả dữ liệu của mình, tùy thuộc vào ứng dụng bên trong.
Barry

14

Nếu bạn chạy docker run <NAME>nó sẽ sinh ra một hình ảnh mới, rất có thể đó không phải là điều bạn muốn.

Nếu bạn muốn thay đổi một hình ảnh hiện tại, hãy làm như sau:

docker ps -a

Lấy id của thùng chứa mục tiêu của bạn và đi đến:

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

Dừng container:

docker stop <NAME>

Thay đổi tập tin

vi config.v2.json

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

Và thay đổi tập tin

vi hostconfig.json

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

Khởi động lại docker của bạn và nó sẽ hoạt động.


2
Điều này không làm việc cho tôi trên Docker phiên bản 17.09.0-ce. Sau khi tôi bắt đầu, tập tin cấu hình bộ chứa đã bị ghi đè trở lại giá trị cũ.
thegeko

3
khởi động lại dịch vụ docker trong hệ thống máy chủ @thegeko
yurenchen

1
những công việc này! tks! 1.stop container, 2.change tập tin, 3. bắt đầu docker, 4.start back container
datdinhquoc 20/11/19

12

Một cách khác xung quanh bạn nếu bạn không thoải mái với IPtables cấu hình độ sâu Docker sẽ là bạn của bạn.

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}

Đây chỉ là một mẹo không phải là cách được đề xuất với kịch bản của tôi bởi vì tôi không thể dừng container, tôi hy vọng cũng sẽ giúp được bạn.


đây là một câu trả lời tuyệt vời Cảm ơn bạn! Nếu tôi muốn ánh xạ DOCKER_PORTtới MACHINE_PORT, những phần nào nên được thay đổi?
Ciprian Tomoiagă

Lưu ý docker wil không biết về bổ sung thủ công này. Các mục SO không bị xóa khi bạn khởi động lại dịch vụ sau đó với docker để lộ các cổng đúng cách. Vì vậy, khi bất cứ điều gì thay đổi, hãy chắc chắn kiểm tra iptables rất cẩn thận. Đặc biệt là tìm kiếm các mục trùng lặp!
anthony

8

chúng tôi sử dụng các công cụ tiện dụng như ssh để thực hiện điều này một cách dễ dàng.

Tôi đã sử dụng máy chủ ubfox và hình ảnh docker dựa trên Ubuntu.

  1. Bên trong docker có cài đặt openssh-client.
  2. Docker bên ngoài (máy chủ) đã cài đặt máy chủ openssh-server.

khi cần một cổng mới để được lập bản đồ,

bên trong docker chạy lệnh sau

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

172.17.0.1 là ip của giao diện docker (bạn có thể lấy cái này bằng cách chạy ifconfig docker0 | grep "inet addr" | cut -f2 -d":" | cut -f1 -d" "trên máy chủ).

Ở đây tôi đã có cổng 8888 cục bộ được ánh xạ trở lại máy chủ 8888. bạn có thể thay đổi cổng khi cần.

nếu bạn cần thêm một cổng, bạn có thể tắt ssh và thêm một dòng -R vào cổng đó với cổng mới.

Tôi đã thử nghiệm điều này với netcat.


2
  1. Dừng động cơ docker và container đó.
  2. Chuyển đến /var/lib/docker/containers/${container_id}thư mục và chỉnh sửahostconfig.json
  3. Chỉnh sửa PortBindings.HostPortrằng bạn muốn thay đổi.
  4. Bắt đầu động cơ docker và container.

0

Là một bổ sung cho phản ứng của @ Fujimoto-Youichi

Bạn cũng có thể sử dụng $ docker run -P CONTAINER để ánh xạ các cổng một cách ngẫu nhiên trong khi tạo vùng chứa của mình, nhưng hãy cẩn thận với sự bảo mật!

-Peq to --publish-all: "Nó xuất bản tất cả các cổng tiếp xúc với các cổng ngẫu nhiên",

sau đó chạy docker inspect CONTAINERđến ánh xạ cổng vây như trong hình bên dưới:

. Docker kiểm tra một container rabbitmq hiển thị tất cả các ánh xạ cổng

Đọc thêm về docker run -PDocker chạy


Đó là KHÔNG thêm cổng vào một container LIVE hiện có!
anthony

Như đã đề cập ở đầu bình luận, nó chỉ là một phần phụ !! Và đối với lệnh: như từ liên kết tài liệu docker được cung cấp: -publish-all, -P Xuất bản tất cả các cổng được hiển thị lên các cổng ngẫu nhiên
ans1genie

-1

Đối với người dùng Windows và Mac, có một cách khá dễ dàng và thân thiện khác để thay đổi cổng ánh xạ:

  1. tải về

  2. đi đến trang cài đặt của container, trên tab cổng, bạn có thể trực tiếp sửa đổi cổng được xuất bản ở đó.

  3. bắt đầu lại container


2
Tôi đã thử phương pháp này. Kinical áp dụng các ánh xạ cổng, thực sự. Tuy nhiên, để áp dụng chúng, nó đã tạo lại container của tôi từ ảnh gốc. Vì vậy, nếu bạn sợ mất các thay đổi được thực hiện trong chính container, không sử dụng phương pháp này.
VeganHunter

1
Tôi thích điều này, tôi nhận ra rằng nó không trả lời câu hỏi và nó tạo ra một thùng chứa mới. Nhưng ít nhất nó hoạt động, và kết quả SO này xuất hiện trong quá trình tìm kiếm của tôi. +1
2b77bee6-5445-4c77-b1eb-4df3e5

-7

Trả lời ngắn: Bạn không thể chỉ định ánh xạ cổng cho bộ chứa Docker hiện có

Bạn cần một container mới ... đối phó với nó.


4
Không cần thái độ. Ngoài ra câu trả lời này là hoàn toàn thiếu chi tiết.
lovefaithswing

1
Không cần chi tiết. Các giai điệu là rất quan trọng để truyền đạt câu trả lời tiết kiệm thời gian này và bản chất phù du của container.
stephen

-11

Nếu bạn chỉ muốn thay đổi cổng của container đang chạy, bạn làm:

  1. dừng container hiện có

    sudo docker dừng NAME

  2. Bây giờ khởi động lại với ánh xạ cổng mới

    sudo docker chạy -d -p 81:80 TÊN

trong khi:

"-d" để làm nền / deamon docker

"-p" cho phép ánh xạ cổng

Cổng "81" bên ngoài (được hiển thị) mà bạn sử dụng để truy cập bằng trình duyệt của mình

Cổng nghe "docker" nội bộ 80 "


4
Điều này chỉ sai. Trong docker runlệnh, NAMElà tên của hình ảnh để chạy một container từ, trong khi ở docker stopcác NAMEđề cập đến tên của các container để dừng lại.
jonatan

1
"Docker run" sẽ tạo ra một container mới. Nó không thể sử dụng cùng tên container với tên đã bị dừng vì bạn chỉ có thể có một container có tên đó. Vì vậy, bạn cần phải làm: "docker stop NAME", docker container rm NAME, sau đó là "docker run -d -p 81:80 NAME" như bạn đã viết.
Lance Kind
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.