Skip to content

Docker

Tham khảo

Khái niệm cơ bản

Bức tranh chung về VM và container xem ở Virtualization Overview. Nhiều container cùng nhau xem Docker Compose.

  • Image: bản đóng gói chỉ đọc gồm filesystem và metadata (lệnh mặc định, biến môi trường...). Image được tạo từ nhiều layer xếp chồng, layer giống nhau được dùng chung và cache lại giữa các image.
  • Container: một tiến trình (hoặc nhóm tiến trình) chạy từ image, có thêm một lớp ghi (writable layer) ở trên cùng. Xóa container thì lớp ghi này mất theo, dữ liệu cần giữ phải đặt ở volume hoặc bind mount.
  • Registry: nơi lưu và phân phối image (Docker Hub, GHCR, registry riêng...). Image được định danh bằng repo:tag.

Container dùng chung kernel của host và được cô lập bằng namespace và cgroups (chi tiết ở Container Internals), nên khởi động nhanh và nhẹ hơn VM nhưng độ cô lập yếu hơn một hypervisor (xem Hypervisor & Hyper-V). Hệ quả thực tế: container Linux chỉ chạy được kernel Linux của host, và các cờ như --privileged làm yếu đáng kể lớp cô lập này.

Cài đặt

Cài đặt Docker Engine trên Ubuntu: https://docs.docker.com/engine/install/ubuntu/

Chạy container

docker run/start/attach

Script dưới đây tạo container từ image ubuntu:20.04 nếu chưa tồn tại, ngược lại thì start (nếu đang Exited) và attach vào container đã có. Container dùng chung user, thư mục $HOME và thư mục làm việc hiện tại với host nên rất tiện cho việc build (ví dụ Petalinux/Yocto).

#!/bin/bash
WRDIR=`pwd`
echo $WRDIR
docker_image_version=20.04
docker_repo=ubuntu

container_name=${docker_repo}_${docker_image_version}
if ! docker ps -a | grep -q $container_name; then
    docker run -t -i -h vubuntu-docker --name=$container_name \
        --privileged=true --net=host \
        -u `id -u`:`id -g` \
        -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro \
        -v /etc/shadow:/etc/shadow:ro -v $HOME:$HOME \
        -v /lib/modules:/lib/modules -v /dev:/dev \
        -v /mnt:/mnt \
        -v $WRDIR:$WRDIR \
        -w $WRDIR $docker_repo:$docker_image_version /bin/bash
elif docker ps -a | grep $container_name | grep -q Exited; then
    docker start $container_name
    docker attach $container_name
else
    docker attach $container_name
fi

docker detach

Thoát khỏi container nhưng vẫn để container chạy: Ctrl + P rồi Ctrl + Q.

docker exec

Mở thêm một shell trong container đang chạy:

docker exec -it <container> bash

Build image

docker build --network=host -t ubuntu-petalinux-20212:20.04 . --progress=plain

Dockerfile mẫu và lưu ý khi build cho môi trường Petalinux/Yocto xem Docker cho môi trường build.

Quản lý container và image

Xem trạng thái

docker ps            # container đang chạy
docker ps -a         # tất cả container, kể cả Exited
docker images        # image trên máy
docker logs -f <container>
docker inspect <container>

Dừng và xóa

docker stop <container>
docker rm <container>
docker rmi <image>

Copy file giữa host và container

docker cp <container>:/path/in/container ./local
docker cp ./local <container>:/path/in/container

Dọn dung lượng

Build Yocto/Petalinux tạo ra image và layer rất lớn, nên dung lượng đĩa dễ đầy.

docker system df            # xem dung lượng Docker đang chiếm
docker image prune          # xóa image dangling
docker container prune      # xóa container đã dừng
docker system prune -a      # xóa tất cả thứ không được dùng (cẩn thận)

Warning

docker system prune -a xóa mọi image không có container nào đang dùng, kể cả image đã mất nhiều giờ để build. Hãy docker push hoặc docker save trước nếu cần giữ lại.

Volume và bind mount

Dữ liệu trong lớp ghi của container sẽ mất khi container bị xóa. Có hai cách chính để giữ dữ liệu hoặc chia sẻ với host:

Bind mount Named volume
Cú pháp -v /host/path:/container/path -v myvol:/container/path
Vị trí lưu Đường dẫn bất kỳ trên host Do Docker quản lý (/var/lib/docker/volumes)
Dùng khi Chia sẻ source code, thư mục build với host Dữ liệu của ứng dụng (database...)

Một số lưu ý với bind mount:

  • File tạo trong container mang UID/GID của user chạy trong container. Nếu chạy bằng root thì file trên host sẽ thuộc root. Đây là lý do script ở trên dùng -u $(id -u):$(id -g), kèm mount /etc/passwd và /etc/group để container nhận ra user host.
  • Thêm :ro để mount chỉ đọc, ví dụ -v /etc/passwd:/etc/passwd:ro.
  • Trên host bật SELinux (Fedora/RHEL) cần thêm :z hoặc :Z.
  • Mount cả $HOME rất tiện nhưng container có thể đọc/ghi mọi thứ trong đó (kể cả ~/.ssh), chỉ nên dùng trên máy dev tin cậy.

Docker Hub

Tạo account Docker Hub bằng tài khoản GitHub. Đẩy image lên Docker Hub:

docker tag local-image:tagname new-repo:tagname
docker push new-repo:tagname

Ví dụ:

docker tag ubuntu-petalinux-20212:20.04 vutang/ubuntu20.04-petalinux:2021.2
docker push vutang/ubuntu20.04-petalinux:2021.2