Tùy chọn --net = host trong lệnh Docker thực sự làm gì?


90

Tôi là một người mới bắt đầu với Docker. Tôi không thể tìm thấy bất kỳ mô tả rõ ràng nào về chức năng của tùy chọn này trong lệnh chạy docker và hơi bối rối về nó.

Chúng tôi có thể sử dụng nó để truy cập các ứng dụng đang chạy trên bộ chứa docker mà không chỉ định cổng không? Ví dụ: nếu tôi chạy một ứng dụng web được triển khai qua hình ảnh docker trong cổng 8080 bằng cách sử dụng tùy chọn -p 8080:8080trong lệnh docker run, tôi biết tôi sẽ phải truy cập nó trên cổng 8080 trên Docker container ip / theWebAppName. Nhưng tôi thực sự không thể nghĩ ra cách --net=hosthoạt động của tùy chọn.

Câu trả lời:


127

Sau khi cài đặt docker, bạn có 3 mạng theo mặc định:

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f3be8b1ef7ce        bridge              bridge              local
fbff927877c1        host                host                local
023bb5940080        none                null                local

Tôi đang cố gắng giữ cho điều này đơn giản. Vì vậy, nếu bạn khởi động một vùng chứa theo mặc định, nó sẽ được tạo bên trong mạng cầu nối (docker0).

$ docker run -d jenkins
1498e581cdba        jenkins             "/bin/tini -- /usr..."   3 minutes ago       Up 3 minutes        8080/tcp, 50000/tcp   friendly_bell

Trong dockerfile của jenkins các cổng 808050000được hiển thị. Các cổng này được mở cho container trên mạng cầu của nó. Vì vậy, mọi thứ bên trong mạng cầu nối đó có thể truy cập vùng chứa trên cảng 808050000. Mọi thứ trong mạng cầu đều nằm trong phạm vi riêng tư của "Subnet": "172.17.0.0/16",Nếu bạn muốn truy cập chúng từ bên ngoài, bạn phải lập bản đồ các cổng -p 8080:8080. Điều này sẽ ánh xạ cổng của vùng chứa của bạn với cổng của máy chủ thực của bạn (mạng máy chủ). Vì vậy, việc truy cập vào máy chủ của bạn trên 8080sẽ định tuyến đến mạng lưới cầu nối của bạn trên cổng 8080.

Bây giờ bạn cũng có mạng máy chủ của mình. Điều này không làm cho kết nối mạng container. Vì vậy, nếu bạn bắt đầu một vùng chứa trong mạng máy chủ, nó sẽ giống như thế này (đó là vùng đầu tiên):

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
1efd834949b2        jenkins             "/bin/tini -- /usr..."   6 minutes ago       Up 6 minutes                              eloquent_panini
1498e581cdba        jenkins             "/bin/tini -- /usr..."   10 minutes ago      Up 10 minutes       8080/tcp, 50000/tcp   friendly_bell

Sự khác biệt là với các cổng. Vùng chứa của bạn hiện nằm trong mạng máy chủ của bạn. Vì vậy, nếu bạn mở cổng 8080trên máy chủ của mình, bạn sẽ tích lũy vùng chứa ngay lập tức.

$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT

Tôi đã mở cổng 8080trong tường lửa của mình và khi tôi đang kết nối máy chủ của mình trên cổng, 8080tôi đang truy cập jenkins của mình. Tôi nghĩ rằng blog này cũng hữu ích để hiểu nó tốt hơn.


4
Có thể thêm tùy chọn --net=hostbên trong Dockerfile không?
AnirbanDebnath 20/02/18

6
@AnirbanDebnath Tôi không nghĩ rằng nó có thể đặt nó trong một dockerfile nhưng vì Docker v17 bạn có thể sử dụng nó như một tham số cho Docker xây dựng của bạn: docker build --network=host. Mạng máy chủ được chỉ định để xây dựng docker chỉ để tải xuống các gói cần thiết để xây dựng hình ảnh. Khi bạn muốn chạy vùng chứa của mình trên mạng máy chủ, bạn vẫn cần xác định tùy chọn --network = host.
lvthillo 20/02/18

Có @AnirbanDebnath, nó được phép trong Dockerfile. ví dụ: Trong v3 - network_mode: "host"(ref - docs.docker.com/compose/compose-file/#network_mode )
Mohnish

Đó là tệp Docker-Compose mô tả cách chạy vùng chứa. Không phải là Dockerfile. Nhưng trên thực tế, nó có thể và làm điều tương tự như docker chạy --network = host
lvthillo

27

Các --net=hosttùy chọn được sử dụng để thực hiện các chương trình bên trong cái nhìn chứa Docker như họ đang chạy trên máy chủ riêng của mình, từ quan điểm của mạng. Nó cho phép vùng chứa truy cập mạng lớn hơn bình thường.

Thông thường, bạn phải chuyển tiếp các cổng từ máy chủ vào một vùng chứa, nhưng khi các vùng chứa chia sẻ mạng của máy chủ, bất kỳ hoạt động mạng nào sẽ xảy ra trực tiếp trên máy chủ - giống như nếu chương trình đang chạy cục bộ trên máy chủ thay vì bên trong thùng đựng hàng.

Mặc dù điều này không có nghĩa là bạn không còn phải để lộ các cổng và ánh xạ chúng đến các cổng vùng chứa nữa, điều đó có nghĩa là bạn phải chỉnh sửa Dockerfiles của mình để điều chỉnh các cổng mà mỗi vùng chứa lắng nghe, để tránh xung đột vì bạn không thể có hai vùng chứa hoạt động trên cùng một tổ cổng. Tuy nhiên, lý do thực sự cho tùy chọn này là để chạy các ứng dụng cần quyền truy cập mạng khó chuyển tiếp tới vùng chứa ở cấp cổng.

Ví dụ, nếu bạn muốn chạy một máy chủ DHCP thì bạn cần phải có khả năng lắng nghe lưu lượng phát sóng trên mạng và trích xuất địa chỉ MAC từ gói tin. Thông tin này bị mất trong quá trình chuyển tiếp cổng, vì vậy cách duy nhất để chạy máy chủ DHCP bên trong Docker là chạy vùng chứa dưới dạng --net=host.

Nói chung, --net=hostchỉ cần thiết khi bạn đang chạy các chương trình có nhu cầu mạng rất cụ thể, bất thường.

Cuối cùng, từ góc độ bảo mật, Docker container có thể lắng nghe trên nhiều cổng, mặc dù chúng chỉ quảng cáo (để lộ) một cổng duy nhất. Thông thường, điều này là tốt vì bạn chỉ chuyển tiếp một cổng mong đợi duy nhất, tuy nhiên nếu bạn sử dụng --net=hostthì bạn sẽ nhận được tất cả các cổng của vùng chứa đang lắng nghe trên máy chủ, ngay cả những cổng không được liệt kê trong Dockerfile. Điều này có nghĩa là bạn sẽ cần phải kiểm tra chặt chẽ vùng chứa (đặc biệt nếu nó không phải của bạn, ví dụ như hộp chính thức được cung cấp bởi một dự án phần mềm) để đảm bảo rằng bạn không vô tình làm lộ các dịch vụ bổ sung trên máy.


Hành vi sẽ như thế nào nếu nhiều vùng chứa được bắt đầu với các tùy chọn '--net = host'? Các yêu cầu có được chuyển tiếp đến một vùng chứa ngẫu nhiên không?
user482594

@ user482594: Tất cả chúng sẽ chia sẻ cùng một ngăn xếp mạng, giống như bạn đã chạy tất cả các chương trình bên trong cùng một vùng chứa. Ví dụ: nếu bạn chạy hai máy chủ web, bạn cần đảm bảo rằng chúng đang lắng nghe trên các cổng khác nhau, nếu không vùng chứa thứ hai sẽ gặp lỗi rằng cổng đang được sử dụng bởi máy chủ thứ nhất. Lưu lượng đến sẽ được chuyển tiếp đến bất kỳ vùng chứa nào đang lắng nghe nó (về mặt kỹ thuật, tất cả các vùng --net=hostchứa sẽ thấy lưu lượng truy cập, nhưng tất nhiên chỉ một chương trình tại một thời điểm có thể nghe trên một cổng nhất định cho dù bạn chạy nó ở vùng chứa nào, trong thiết lập này ).
Malvineous

1
  1. bạn có thể tạo mạng mới của riêng mình như --net = "anyname"
  2. điều này được thực hiện để cô lập các dịch vụ khỏi các vùng chứa khác nhau.
  3. giả sử cùng một dịch vụ đang chạy trong các vùng chứa khác nhau, nhưng ánh xạ cổng vẫn giống nhau, vùng chứa đầu tiên khởi động tốt, nhưng cùng một dịch vụ từ vùng chứa thứ hai sẽ không thành công. vì vậy để tránh điều này, hãy thay đổi ánh xạ cổng hoặc tạo mạng.

1
Cảm ơn bạn đã đề cập đến "2. điều này được thực hiện để cô lập các dịch vụ (mạng) khỏi các vùng chứa khác nhau". Tôi thực sự thấy giá trị của việc sử dụng các cấu hình mạng docker khác (không phải host) nếu có khả năng chạy nhiều vùng chứa trên cùng một máy chủ. Trong các trường hợp khác (không yêu cầu cách ly mạng), tôi thích hơn --net=host.
CᴴᴀZ
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.