Tìm hiểu Docker (Phần 2)
Ở bài trước chúng ta đã tìm hiểu về các khái niệm của Docker, cách quản lý với images, container. Hôm nay mình sẽ giới thiệu cho các bạn về các thành phần khác của docker. 1. Docker Hub 1.1. Tag và Push image Như ở bài trước mình đã định nghĩa Docker Hub là dịch vụ cloud để chia sẻ ứng dụng ...
Ở bài trước chúng ta đã tìm hiểu về các khái niệm của Docker, cách quản lý với images, container. Hôm nay mình sẽ giới thiệu cho các bạn về các thành phần khác của docker.
1. Docker Hub
1.1. Tag và Push image
Như ở bài trước mình đã định nghĩa Docker Hub là dịch vụ cloud để chia sẻ ứng dụng và tự động hóa chuỗi các công việc liên tục, có thể thao tác pull/push với các images.
Docker Hub cung cấp các tính năng sau:
- Repository: Tìm, quản lý và đẩy và kéo images từ cộng đồng, chính thức, và các thư viện riêng.
- Automated Builds: Tự động tạo ra images mới khi bạn thay đổi một source code repository.
- Webhooks: Một tính năng của Automated Builds, Webhooks cho phép bạn kích hoạt các hành động sau khi đẩy thành công lên repo.
- Organizations: Tạo các nhóm làm việc để quản lý quyền truy cập vào kho repo.
- GitHub và tích hợp Bitbucket: Thêm các Hub và Docker image tới công việc hiện tại của bạn.
Vậy để có thể thao tác với Docker Hub, điều đầu tiên là các bạn phải đăng ký tài khoản tại đây Sau khi tạo account, các bạn sẽ tạo tiếp cho mình 1 Repository.
- Chọn Create Repository.
- Điền tên Repository và Description.
- Chọn Public.
- Ấn Create
Ví dụ:
Để tag và push được 1 image lên server, trước hết chúng ta cần check images có trên server:
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cuongtv/ubuntu new a40b24baadc1 21 months ago 320.5 MB
Hiện tại trên server có 1 images là a40b24baadc1
Ta sẽ tag images này:
# docker tag a40b24baadc1 cuongtv/ubuntu:update
trong đó
- docker: lệnh chạy docker
- tag: subcommand
- a40b24baadc1: ID images
- cuongtv: tên account docker hub (vừa tạo)
- ubuntu: tên images
- update: số version hoặc tag
Chú ý: Khi push 1 images, namespace khi tag không phải là tên Repository mà trùng với tên account docker hub. và phải chuyển images về dạng docker_hub_account/images_name
Kiểm tra lại images:
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE cuongtv/ubuntu new a40b24baadc1 21 months ago 320.5 MB cuongtv/ubuntu update a40b24baadc1 21 months ago 320.5 MB
ok. đã có thêm 1 tag là update xuất hiện.
Login vào Docker hub với câu lệnh
docker login --username=yourhubusername --email=youremail@company.com
VD:
# docker login --username=cuongtv --email=cuongtv2004@gmail.com Flag --email has been deprecated, will be removed in 1.13. Password: Login Succeeded
ok. giờ chỉ việc push images đó lên là xong. ta dùng:
# docker push cuongtv/ubuntu:update The push refers to a repository [docker.io/cuongtv/ubuntu] 242866a1a267: Layer already exists 7c3ed71f0e62: Layer already exists 5f70bf18a086: Layer already exists 94c37152acf4: Layer already exists ceddf6185bdf: Layer already exists 874f34b4a164: Layer already exists cb901f44f2d9: Layer already exists 6677dd8955a6: Layer already exists update: digest: sha256:1de164927e42443e50309f4cf96cd2a6c025ba302d18df7ecb2f49bba065fdde size: 2400
Kiểm tra trên Docker Hub
ok. đã push thành công
1.2. Pull images từ Docker Hub
Nếu trên máy các bạn chưa có images nào thì các bạn có thể pull dễ dàng với command: docker pull <namespace>/<image_name>:<tag>
VD: docker pull cuongtv/ubuntu:update
Còn nếu trong máy đã có images đó và muốn pull lại thì trước hết các bạn phải xóa images đi.
Check images:
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest f8d79ba03c00 13 days ago 126.4 MB cuongtv/ubuntu new a40b24baadc1 21 months ago 320.5 MB cuongtv/ubuntu update a40b24baadc1 21 months ago 320.5 MB
Xóa images bằng:
# docker rmi -f a40b24baadc1 Untagged: cuongtv/ubuntu:new Untagged: cuongtv/ubuntu:update Untagged: cuongtv/ubuntu@sha256:1de164927e42443e50309f4cf96cd2a6c025ba302d18df7ecb2f49bba065fdde Untagged: cuongtv/ubuntu@sha256:c6aac3d7ddc6d347bcce7a7ec0789e856dba59c66c86d823ba7d9fb4381397b5 Deleted: sha256:a40b24baadc1fd42bcb2daf5df75797f51bbd730e1da820cf72d9d70c33bacef Deleted: sha256:05754264db23c58d7cf7d87d65a27490f54888e0a0bb651e3040be55a8e99c23 Deleted: sha256:30d72f24fecc7059e238719786ecc86d14a747e3d361270704462740cfb6219d Deleted: sha256:39605e01bb73b2e6d3e9f7cb4ef8882df57a9624b7e2b1ba8bb50731782621d6 Deleted: sha256:a08af43f039d8e97f1fe64b661fdad124c2d57039717fb4e1b5967dbddd7fb4c Deleted: sha256:442e4e0e4ce16a587bdbac66004ba21cbfec997f032a7c6b13a0f8eec63d9b30 Deleted: sha256:42f8d0269dd544191bfbc031495c308d94117acda1f54a846c79666482a6f1de Deleted: sha256:fcc6ef58250f1290b5b16551190dfb74a6119b4ef48e00ad8ffa46568251c172 Deleted: sha256:5a0990c9f12a2b1f5f4fcca7dcda5d16d8b9187c97cdce467ec7b14e9484adce Deleted: sha256:b5aa333d6e4afb2eda7dcfac605a7b6a5fe3c85e18af7ca29fa1e779d2bd3541 Deleted: sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef
check lại images:
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest f8d79ba03c00 13 days ago 126.4 MB
Done. đã sạch images mà chúng ta muốn xóa. OK. giờ làm lại pull theo bước vừa rồi.
# docker pull cuongtv/ubuntu:update
Check images:
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest f8d79ba03c00 13 days ago 126.4 MB cuongtv/ubuntu update a40b24baadc1 21 months ago 320.5 MB
Đó mới là những phần cơ bản nhất của Docker. Chúng ta sẽ tìm hiểu thêm
2. Docker run
Chúng ta đã biết cách quản lý images, vậy muốn chạy chương trình trong images thì ta phải làm như thế nào? Vâng Docker run sẽ giải quyết bài toán này.
Để chạy với 1 container:
# docker run cuongtv/ubuntu:update /bin/echo "hello" hello
với:
- docker run: chạy container
- cuongtv/ubuntu:update: sử dụng images được tag để chạy container
- /bin/echo: câu lệnh chạy trong container
Để chạy câu lệnh trực tiếp trong container (jump vào container)
# docker run -t -i cuongtv/ubuntu:update /bin/bash root@b34a0b5e1062:/#
tham số -d Để chạy container với background (ko shutdown khi thoát)
# docker run -d cuongtv/ubuntu:update /bin/sh -c "while true; do echo hello world; sleep 1; done" # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e9bb693c09ce cuongtv/ubuntu:update "/bin/sh -c 'while tr" 5 seconds ago Up 3 seconds big_mayer
Sau đó ta phải stop bằng tay
# docker stop e9bb693c09ce e9bb693c09ce
Tham số -p để gán port cho docker
# docker run -d -p 8080:80 nginx Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx 357ea8c3d80b: Pull complete 0fc04568277e: Pull complete 0bed9719ddcb: Pull complete Digest: sha256:d33834dd25d330da75dccd8add3ae2c9d7bb97f502b421b02cecb6cb7b34a1b6 Status: Downloaded newer image for nginx:latest c540fb623bbdce173a34cfbaca0a0e05c151f0d37e1b5164cfdb07cf923b2c2e
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c540fb623bbd nginx "nginx -g 'daemon off" 14 seconds ago Up 12 seconds 443/tcp, 0.0.0.0:8080->80/tcp tiny_ramanujan
Ta thấy
port 0.0.0.0:8080->80/tcp
port 8080 trên container đã được gán ra ngoài. Vậy có thể truy cập nginx với link: http://<ip_server_host>:8080 để kiểm tra.
3. Network trong Docker
Khi bạn cài đặt Docker, mặc định 3 mạng được tạo ra. Bạn có thể list những mạng này bằng câu lệnh docker network ls
# docker network ls NETWORK ID NAME DRIVER SCOPE f8e060b83952 bridge bridge local 3120118683f2 host host local 6b857938ab70 none null local
3 mạng này đều là thành phần của Docker. Khi bạn chạy 1 container có --network thì nó sẽ chỉ định trực tiếp mạng nào mà bạn muốn container chạy trên đó.
Bridge: là mạng mặc định chạy với Docker nếu không có option --network đi cùng. Bridge như 1 phần của mạng host.
# ifconfig docker0 Link encap:Ethernet HWaddr 02:42:eb:c3:f3:05 inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:ebff:fec3:f305/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:51 errors:0 dropped:0 overruns:0 frame:0 TX packets:35 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:4564 (4.5 KB) TX bytes:2917 (2.9 KB)
None: Nó hoàn toàn disable card mạng đi. Bạn có thể nhìn thấy bằng cách:
$ docker attach nonenetcontainer root@0cb243cd1293:/# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters root@0cb243cd1293:/# ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Host: là mạng chỉ gắn container với host ngoài. Bạn sẽ thấy container có cấu hình mạng hệt như host. Bạn có thể thay đổi cấu hình trực tiếp của host nếu thay đổi IP của container.
3.1. Bridge network
Mạng Bridge tồn tại trên tất cả các host. Câu lệnh Docker network inspect cho thấy:
root@test-registry:~# docker network inspect bridge [ { "Name": "bridge", "Id": "f8e060b83952bcb6cc810ba4f203448103e679d18c4b18852bc107f3d5b68461", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Containers": { "c540fb623bbdce173a34cfbaca0a0e05c151f0d37e1b5164cfdb07cf923b2c2e": { "Name": "tiny_ramanujan", "EndpointID": "daac15638d5ca5cb5482d7ec2382146261127a0af6fb5efdddd712868d782618", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
Engine sẽ tự tạo Subnet và Gateway cho mạng này. Ta sẽ add 1 số container vào mạng này.
# docker run -itd --name=CT1 busybox Unable to find image 'busybox:latest' locally latest: Pulling from library/busybox 8ddc19f16526: Pull complete Digest: sha256:a59906e33509d14c036c8678d687bd4eec81ed7c4b8ce907b888c607f6a1e0e6 Status: Downloaded newer image for busybox:latest a510402ee35475237d9d739d41a6b108fdda208a19a62d3c7929e2b7866e542b root@test-registry:~# docker run -itd --name=CT2 busybox 3a747458fbffc70f55b363ba9452ef608ef5e478e26d054630ffe79d9f1db35a
Inspect đã cho thấy add thêm CT1 và CT2 vào
# docker network inspect bridge [ { "Name": "bridge", "Id": "f8e060b83952bcb6cc810ba4f203448103e679d18c4b18852bc107f3d5b68461", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Containers": { "3a747458fbffc70f55b363ba9452ef608ef5e478e26d054630ffe79d9f1db35a": { "Name": "CT2", "EndpointID": "28a1a4aaae8e98bc0657f14d628615fe53033ace13eda36b6ccad031c84b9d4a", "MacAddress": "02:42:ac:11:00:04", "IPv4Address": "172.17.0.4/16", "IPv6Address": "" }, "a510402ee35475237d9d739d41a6b108fdda208a19a62d3c7929e2b7866e542b": { "Name": "CT1", "EndpointID": "fff1a1d7d9da8a12ba969dac44d206fceb73dbebff4ae785ed4e418c63a012ff", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" }, "c540fb623bbdce173a34cfbaca0a0e05c151f0d37e1b5164cfdb07cf923b2c2e": { "Name": "tiny_ramanujan", "EndpointID": "daac15638d5ca5cb5482d7ec2382146261127a0af6fb5efdddd712868d782618", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} }
Câu lệnh docker network inspect cho biết tất cả các container đang kết nối tới mạng đó. Container trong mạng default có thể giao tiếp với nhau bằng IP. Docker không hỗ trợ việc tự động phát hiện dịch vụ trên bridge network. Nếu bạn muốn giao tiếp giữa các container trong bridge network thì phải kết nối chúng với nhau thông qua docker run --link
Bạn có thể attach 1 container đang chạy:
# docker attach CT1 / # ping 172.17.0.4 PING 172.17.0.4 (172.17.0.4): 56 data bytes 64 bytes from 172.17.0.4: seq=0 ttl=64 time=0.221 ms 64 bytes from 172.17.0.4: seq=1 ttl=64 time=0.136 ms ^C --- 172.17.0.4 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.136/0.178/0.221 ms / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03 inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:20 errors:0 dropped:0 overruns:0 frame:0 TX packets:12 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1576 (1.5 KiB) TX bytes:928 (928.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Để detach từ container CT1 sử dụng CTRL-p CTRL-q. Tiếp tục test với container CT2 ở mạng bridge
# docker attach CT2 / # ping 172.17.0.3 PING 172.17.0.3 (172.17.0.3): 56 data bytes 64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.128 ms 64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.130 ms # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:04 inet addr:172.17.0.4 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:acff:fe11:4/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:20 errors:0 dropped:0 overruns:0 frame:0 TX packets:18 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1488 (1.4 KiB) TX bytes:1348 (1.3 KiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:2 errors:0 dropped:0 overruns:0 frame:0 TX packets:2 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:168 (168.0 B) TX bytes:168 (168.0 B)
Mặc định Bridge network docker0 hỗ trợ map port và docker run --link để cho phép các container giao tiếp với nhau qua card mạng docker0.
3.2. User-defined networks
Bạn có thể tạo ra các mạng tự định nghĩa để cô lập các container. Docker cung cấp 1 vài loại mạng: bridge network, overlay network, MACVLAN network.
Bạn có thể tạo nhiều mạng khác nhau và add container vào nhiều mạng khác nhau. Các container cùng mạng thì chúng có thể tự nói chuyện được với nhau nhưng không thể nói chuyện được với các mạng bên ngoài.
Cách dễ nhất để tạo 1 mạng tự định nghĩa là dùng bridge network. VD
# docker network create --driver bridge network_1 34de3f1c049db329e5bf593c73e32a62683a5fad3d220c1d62abbcf8cfb0de5d root@test-registry:~# docker network inspect network_1 [ { "Name": "network_1", "Id": "34de3f1c049db329e5bf593c73e32a62683a5fad3d220c1d62abbcf8cfb0de5d", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1/16" } ] }, "Internal": false, "Containers": {}, "Options": {}, "Labels": {} } ]
Sau khi tạo xong network_1 bạn có thể chạy container = cách sử dụng docker run --network=<network>
# docker run --network=network_1 -itd --name=CT3 busybox d2cc9cc095820f07a187e33be08f002a1dfe88dacee8a42d962a48f8243c1015 root@test-registry:~# docker network inspect network_1 [ { "Name": "network_1", "Id": "34de3f1c049db329e5bf593c73e32a62683a5fad3d220c1d62abbcf8cfb0de5d", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1/16" } ] }, "Internal": false, "Containers": { "d2cc9cc095820f07a187e33be08f002a1dfe88dacee8a42d962a48f8243c1015": { "Name": "CT3", "EndpointID": "a172935834efb325abb0dd326c1f6ff3968e9b075bae710ebea16bd98e9f900b", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
Trong mạng tự xác định, link không được hỗ trợ. Bạn chỉ có thể publish port trên mạng này ra ngoài.
Bridge network thì hữu dụng trong những trường hợp bạn muốn chạy trên 1 mạng nhỏ hoặc 1 host duy nhất. Bạn cũng có thể tạo ra mạng lớn hơn với overlay network.
Phần tiếp theo chúng ta sẽ nghiên cứu tiếp về swarm mode và overlay network.