+2

Cách gán ip tĩnh (static ip) cho container

Giới thiệu

Docker, Virtual Machine, ... nói chung đều là các công nghệ ảo hóa, tức thay vì phải dùng phần cứng vật lý, chúng ta có thể tạo chúng chỉ bằng vài thao tác đơn giản: click chuột, kéo thả để tạo ổ đĩa, nhập số lượng cpu, ram, click chuột để tạo card mạng, nhập địa chỉ ip, ... Trong bài này mình sẽ giới thiệu cách gán ip tĩnh cho docker container, mục tiêu để hiểu hơn về network của docker cũng như vận dụng chúng vào một mục tiêu cụ thể.

Với docker, khi khởi tạo container bằng lệnh docker run docker daemon (docker backend) sẽ gắn vào container đó một network, mặc định là bridge, để xem các loại network mà docker hỗ trợ các bạn có thể xem thêm ở đây, network bridge này sẽ gán ngẫu nhiên một ip mà chưa được sử dụng cho container, thông tin này có thể được trích xuất bằng lệnh docker inspect <container-name-or-id>

tuana9a@tuana9a-XPS-13-9370:~$ docker run -d nginx
b875d4a6ef1b69ab5f865e4d2831169e025d3de20a069a0a9c58c1474a7b4e4a
tuana9a@tuana9a-XPS-13-9370:~$ docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS        PORTS     NAMES
b875d4a6ef1b   nginx     "/docker-entrypoint.…"   3 seconds ago   Up 1 second   80/tcp    loving_booth
tuana9a@tuana9a-XPS-13-9370:~$ docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' loving_booth 
172.17.0.2
tuana9a@tuana9a-XPS-13-9370:~$ 
tuana9a@tuana9a-XPS-13-9370:~$ docker run -d nginx
2e427673ce4e73f218fbfc99dc63608c83c123e1a116f3ef22c5015da2f4da6b
tuana9a@tuana9a-XPS-13-9370:~$ docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
2e427673ce4e   nginx     "/docker-entrypoint.…"   2 seconds ago   Up 2 seconds   80/tcp    quizzical_swirles
b875d4a6ef1b   nginx     "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   80/tcp    loving_booth
tuana9a@tuana9a-XPS-13-9370:~$ docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' quizzical_swirles 
172.17.0.3
tuana9a@tuana9a-XPS-13-9370:~$ 

Dễ thấy mỗi lần chạy docker run thì container sẽ được gán một ip mới được cấp tự động bởi docker daemon. Qua đó mình có thể hiểu sơ sơ về cơ chế networking của docker vậy làm sao để có thể gán ip tùy ý cho container này? Các bạn có thể search từ khóa cho việc gán ip tĩnh này là docker user defined network.

Bắt đầu gán ip tĩnh nào

Do nếu sử dụng network mặc định thì docker sẽ gán ip ngẫu nhiên cho container nên để gán ip tĩnh, trước tiên các bạn cần tự định nghĩa (tạo) một network mới:

docker network create --subnet=172.209.0.0/16 net1

Trong đó 172.209.0.0/16 là dải ip cho network có tên là net1 (bạn nào không hiểu dải ip - CIDR là gì thì học lại môn mạng máy tính nhé), tên network trong docker là unique nên bạn hãy chọn một cái tên thật hay và ý nghĩa nhé, còn không thì cứ i=i+1, net1, net2, net3 như mình.

Kiểm tra

tuana9a@tuana9a-XPS-13-9370:~$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
95fb54d16918   bridge    bridge    local
1a83bd3f1eed   host      host      local
a7e75a7f1e35   net1      bridge    local # cái mình mới tạo nè
8059d3896bb6   none      null      local

Các bạn có thể chạy lệnh docker inspect network net1 và tự sướng.

Giờ tạo được network theo ý mình rồi giờ dùng sao? Thêm flag --network và tên network net1 sau đó là --ip và ip tĩnh khi khởi chạy container bằng lệnh docker run là được.

docker run --name nginx1 --net net1 --ip 172.209.0.2 -d nginx

Kiểm tra ip của thằng này

tuana9a@tuana9a-XPS-13-9370:~$ docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx1
172.209.0.2

Ping thử xem được không

tuana9a@tuana9a-XPS-13-9370:~$ ping 172.209.0.2 -c 3
PING 172.209.0.2 (172.209.0.2) 56(84) bytes of data.
64 bytes from 172.209.0.2: icmp_seq=1 ttl=64 time=0.054 ms
64 bytes from 172.209.0.2: icmp_seq=2 ttl=64 time=0.069 ms
64 bytes from 172.209.0.2: icmp_seq=3 ttl=64 time=0.048 ms

--- 172.209.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2030ms
rtt min/avg/max/mdev = 0.048/0.057/0.069/0.008 ms

Cũng được luôn. Không biết 2 container cùng chung network net1 đấy có ping được nhau không, để chắc cú chạy thêm thằng nginx2 nữa rồi kiểm tra

docker run --name nginx2 --net net1 --ip 172.209.0.3 -d nginx

Kiểm tra

tuana9a@tuana9a-XPS-13-9370:~$ docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
681df3464e0c   nginx     "/docker-entrypoint.…"   6 minutes ago   Up 6 minutes   80/tcp    nginx2
89566925a1bf   nginx     "/docker-entrypoint.…"   8 minutes ago   Up 8 minutes   80/tcp    nginx1
tuana9a@tuana9a-XPS-13-9370:~$ 

Giờ để ping nginx1 từ nginx2 chúng ta cần chui vào nginx2, câu lệnh để chui vào như sau, quý lắm mới cho biết đấy:

docker exec -it nginx2 bash

Trong đó

  • docker exec là lệnh để thực hiện command trong container
  • nginx2 là tên container muốn chui vô
  • bash là lệnh muốn thực thi trong container, ngoài bash thì còn sh, đại loại shell nào mà container nó hỗ trợ đều đươc, shell trong linux là gì á, Google giúp mình với.
  • -it là flag để tương tác với bash từ bàn phím và terminal được, bạn không tin thì bỏ thử -it mà xem.
tuana9a@tuana9a-XPS-13-9370:~$ docker exec -it nginx2 bash
root@681df3464e0c:/# 
root@681df3464e0c:/# ping 172.209.0.2 -c 3 
bash: ping: command not found

ẹc, thôi dùng curl xem được không

root@681df3464e0c:/# curl 172.209.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@681df3464e0c:/# 

Được nè, vậy 2 container chung custom network có thể truy cập với nhau bằng ip được, vậy 2 container khác network thì sao. Tạo thằng thứ 3 nào, lần này tạo với network mặc định xem sao.

docker run --name nginx3 -d nginx
tuana9a@tuana9a-XPS-13-9370:~$ docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
cadad914704e   nginx     "/docker-entrypoint.…"   6 minutes ago    Up 6 minutes    80/tcp    nginx3
681df3464e0c   nginx     "/docker-entrypoint.…"   46 minutes ago   Up 46 minutes   80/tcp    nginx2
89566925a1bf   nginx     "/docker-entrypoint.…"   48 minutes ago   Up 48 minutes   80/tcp    nginx1
tuana9a@tuana9a-XPS-13-9370:~$ 

Các bạn thử inspect xem ip của thằng nginx3 này là bao nhiêu? Giờ thì chui vào thằng nginx3 Kiểm tra

tuana9a@tuana9a-XPS-13-9370:~$ docker exec -it nginx3 bash
root@cadad914704e:/# curl 172.209.0.2
curl: (28) Failed to connect to 172.209.0.2 port 80 after 129416 ms: Couldn't connect to server
root@cadad914704e:/#

Vậy khác network không được hả. hmm, giải thích theo kiểu mục đích sử dụng thì nếu ông muốn 2 container nói chuyện với nhau thì cho chúng nó chung network đi, còn không muốn nói chuyện với nhau thì đi mà tạo một cái network riêng và thế là không nói chuyện được với nhau.

Còn từ doc của docker https://docs.docker.com/network/drivers/bridge/

In terms of Docker, a bridge network uses a software bridge which lets containers connected to the same bridge network communicate, while providing isolation from containers that aren't connected to that bridge network. The Docker bridge driver automatically installs rules in the host machine so that containers on different bridge networks can't communicate directly with each other.

À ra là vậy, đại loại docker họ ghi rất rõ là không cho phép 2 container khác network nói chuyện với nhau.

Thế là từ giờ tôi đã có thể làm chủ các con số trong cuộc đời mình, yay.

BONUS

Mỗi lần muốn gán ip mà phải chạy lệnh kia thì hơi ỉ*, thế dùng docker-compose được không

Được

version: "2"

services:
  nginx1:
    image: nginx
    networks:
      net1:
        ipv4_address: 172.209.0.2
  nginx2:
    image: nginx
    networks:
      net1:
        ipv4_address: 172.209.0.3

networks:
  net1: # name of docker network
    ipam:
      config:
        - subnet: 172.209.0.0/16

Hết.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí