Viblo Learning
+1

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 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ụ:

Screenshot_21.png

Để 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 protected]

VD:

# docker login --username=cuongtv [email protected]
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 Screenshot_1.png

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/[email protected]:1de164927e42443e50309f4cf96cd2a6c025ba302d18df7ecb2f49bba065fdde
Untagged: cuongtv/[email protected]: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
[email protected]:/#

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

[email protected]:/# 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
[email protected]:/# 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:

[email protected]:~# 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
[email protected]:~# 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
[email protected]:~# 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
[email protected]:~# 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.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.