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 containernginx2
là tên container muốn chui vôbash
là lệnh muốn thực thi trong container, ngoàibash
thì cònsh
, đạ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