Reading Time: 21 minutes

Mở đầu

Docker là một nền tảng giúp đơn giản hóa quá trình triển khai và quản lý ứng dụng bằng cách sử dụng công nghệ container. Containers cho phép bạn chạy ứng dụng trong các tiến trình được cách ly tài nguyên, mang lại sự ổn định và bảo mật cao hơn. Mặc dù có điểm tương đồng với máy ảo (Virtual Machine), nhưng containers nhẹ hơn, linh hoạt hơn và tận dụng tốt hơn tài nguyên hệ thống và phụ thuộc nhiều hơn vào hệ điều hành của máy chủ.

Nếu bạn đang muốn bắt đầu với Docker trên Ubuntu, thì đây chính là bài viết dành cho bạn. Trong hướng dẫn này, mình sẽ cùng bạn từng bước cài đặt Docker Community Edition (CE) phiên bản miễn phí, phổ biến nhất của Docker.

Không chỉ đơn thuần là cài đặt, bạn sẽ được thực hành các thao tác cơ bản như:

  • Làm quen với containers và images.
  • Tạo và quản lý containers (bắt đầu, dừng, xoá).
  • Tự tạo Docker image từ những thay đổi trong container.
  • Đẩy image lên Docker Hub (hoặc repository riêng của bạn).

Bên cạnh đó, mình cũng sẽ hướng dẫn bạn cách:

  • Cài Docker có hỗ trợ GPU (nếu bạn dùng cho AI/ML).
  • Xử lý một số lỗi phổ biến trong quá trình sử dụng.
  • Và chia sẻ vài mẹo bảo mật để bạn yên tâm khi dùng Docker trong dự án thực tế.

Trước khi bắt đầu, bạn cần chuẩn bị gì?

Để quá trình cài đặt Docker diễn ra suôn sẻ, hãy đảm bảo bạn đáp ứng một vài điều kiện sau:

  • Một máy chủ Ubuntu đã được cấu hình cơ bản, bao gồm:
    • Người dùng không phải root nhưng có quyền sudo.
    • Tường lửa (firewall) đã được thiết lập theo hướng dẫn khởi tạo server của Ubuntu.
  • Một tài khoản Docker Hub bạn có thể đăng ký miễn phí tại https://hub.docker.com để lưu trữ và chia sẻ các Docker image sau này.

Khi mọi thứ đã sẵn sàng, chúng ta hãy cùng bắt đầu hành trình cài đặt Docker trên Ubuntu.

Bước 1: Cài đặt Docker trên Ubuntu

Mặc dù Ubuntu đã cung cấp sẵn gói cài đặt Docker trong kho lưu trữ của mình, nhưng phiên bản đó thường không phải là mới nhất.

Để đảm bảo chúng ta sử dụng phiên bản Docker mới nhất với đầy đủ tính năng và bản vá bảo mật, mình sẽ hướng dẫn bạn cài đặt Docker trực tiếp từ kho lưu trữ chính thức của Docker.

Quy trình sẽ gồm các bước:

  • Thêm nguồn chứa gói Docker chính thức vào hệ thống.
  • Thêm khóa GPG để xác thực các tệp cài đặt, đảm bảo chúng an toàn và đáng tin cậy.
  • Tiến hành cài đặt Docker từ nguồn mới này.

Trước khi cài đặt bất kỳ phần mềm mới nào, việc đầu tiên chúng ta nên làm là cập nhật danh sách các gói của hệ thống. Điều này giúp đảm bảo mọi thứ đều mới nhất và tránh lỗi trong quá trình cài đặt.

sudo apt update

Tiếp theo, chúng ta cần cài đặt một số gói phụ trợ. Những gói này cho phép apt có thể giao tiếp và lấy các gói phần mềm thông qua giao thức HTTPS một giao thức an toàn và bảo mật hơn.

sudo apt install apt-transport-https ca-certificates curl software-properties-common

Để đảm bảo các gói cài đặt Docker mà chúng ta tải về là hợp lệ và chưa bị thay đổi, chúng ta cần thêm khóa GPG chính thức của Docker vào hệ thống.

curl -fsSL <https://download.docker.com/linux/ubuntu/gpg> | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Sau khi đã thêm khóa GPG, bước tiếp theo là thêm kho lưu trữ chính thức của Docker vào danh sách nguồn của apt. Điều này giúp hệ thống nhận biết và cài đặt Docker trực tiếp từ nguồn đáng tin cậy.

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] <https://download.docker.com/linux/ubuntu> $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Bây giờ chúng ta cần cập nhật lại danh sách gói một lần nữa để hệ thống nhận diện được nguồn mới vừa thêm vào.

sudo apt update

Lệnh này sẽ quét tất cả các nguồn phần mềm (bao gồm kho Docker mới) và cập nhật thông tin về các gói phần mềm khả dụng. Trước khi tiến hành cài đặt, chúng ta cần đảm bảo rằng apt sẽ lấy Docker từ kho lưu trữ chính thức của Docker, chứ không phải từ kho mặc định của Ubuntu (vì kho mặc định có thể chứa phiên bản cũ hơn).

apt-cache policy docker-ce

Bạn sẽ thấy kết quả đầu ra tương tự như thế này (lưu ý rằng số phiên bản Docker có thể khác tuỳ thời điểm):

docker-ce:
  Installed: (none)
  Candidate: 5:20.10.14~3-0~ubuntu-jammy
  Version table:
     5:20.10.14~3-0~ubuntu-jammy 500
        500 <https://download.docker.com/linux/ubuntu> jammy/stable amd64 Packages
     5:20.10.13~3-0~ubuntu-jammy 500
        500 <https://download.docker.com/linux/ubuntu> jammy/stable amd64 Packages

Lưu ý rằng docker-ce chưa được cài đặt trên hệ thống của bạn (bạn sẽ thấy “Installed: (none)”). Tuy nhiên, thông tin (candidate) cho chúng ta biết phiên bản cài đặt từ kho lưu trữ chính thức của Docker dành cho Ubuntu, điều này có nghĩa là bạn sẽ cài đặt phiên bản mới nhất từ Docker chứ không phải phiên bản cũ hơn từ kho lưu trữ mặc định của Ubuntu.

Giờ thì chúng ta đã sẵn sàng để cài đặt Docker từ kho lưu trữ chính thức! Để cài đặt Docker Engine, chỉ cần chạy lệnh sau trong terminal:

sudo apt install docker-ce

Đợi quá trình cài đặt hoàn tất, Docker sẽ tự động được khởi động và thiết lập để bắt đầu mỗi khi hệ thống khởi động lại.

Để kiểm tra xem Docker có đang chạy không, bạn chỉ cần chạy lệnh sau:

sudo systemctl status docker

Output● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2022-04-01 21:30:25 UTC; 22s ago
TriggeredBy: ● docker.socket
       Docs: <https://docs.docker.com>
   Main PID: 7854 (dockerd)
      Tasks: 7
     Memory: 38.3M
        CPU: 340ms
     CGroup: /system.slice/docker.service
             └─7854 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Sau khi cài đặt Docker, bạn không chỉ có dịch vụ Docker (daemon) mà còn có công cụ dòng lệnh docker, hay còn gọi là Docker client. Công cụ này cho phép bạn tương tác với Docker và quản lý các container, images, networks và volumes. Với Docker client, bạn có thể dễ dàng thực hiện các lệnh để xây dựng, chạy và quản lý containers của mình từ terminal. Chúng ta sẽ cùng tìm hiểu cách sử dụng các lệnh Docker trong phần sau của hướng dẫn này.

Bước 2: Thực thi lệnh Docker mà không cần sudo

Theo mặc định, lệnh docker chỉ có thể được thực thi bởi người dùng root hoặc bởi những người dùng đã được thêm vào nhóm docker, nhóm này được tạo tự động trong quá trình cài đặt Docker. Nếu bạn cố gắng chạy lệnh docker mà không sử dụng sudo hoặc không thuộc nhóm docker, bạn sẽ nhận được thông báo lỗi giống như sau:

Outputdocker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?.
See 'docker run --help'.

Tuy nhiên, nếu bạn không muốn luôn phải thêm sudo vào mỗi lệnh Docker, bạn có thể thêm người dùng của mình vào nhóm docker. Điều này sẽ cho phép bạn chạy các lệnh Docker mà không cần quyền root.

sudo usermod -aG docker $USER

Để áp dụng quyền truy cập mới sau khi thêm người dùng vào nhóm docker, bạn cần phải đăng xuất khỏi hệ thống và đăng nhập lại.

su - ${USER}

Để xác nhận rằng người dùng của bạn đã được thêm thành công vào nhóm docker, bạn có thể sử dụng lệnh sau:

groups $USER

Lệnh này sẽ hiển thị tất cả các nhóm mà người dùng hiện tại thuộc về. Nếu bạn thấy docker trong danh sách nhóm, điều này có nghĩa là người dùng đã được thêm vào nhóm docker thành công.

Phần còn lại của bài viết này giả định rằng bạn đang chạy lệnh docker với quyền của người dùng đã được thêm vào nhóm docker. Bây giờ, chúng ta sẽ cùng tìm hiểu một số lệnh cơ bản của Docker để bắt đầu sử dụng công cụ này. Docker cung cấp một bộ lệnh mạnh mẽ giúp bạn quản lý containers, images, networks, và volumes.

Bước 3: Sử dụng Lệnh Docker

Việc sử dụng Docker bao gồm việc truyền cho Docker một chuỗi các tùy chọn và lệnh, theo sau là các đối số cần thiết. Cú pháp của lệnh Docker có dạng như sau:

docker [OPTIONS] COMMAND [ARGUMENTS...]
  • OPTIONS: Các tùy chọn này có thể điều chỉnh cách thức lệnh được thực thi, chẳng hạn như chế độ tương tác, hạn chế tài nguyên, hoặc chỉ định các cài đặt cụ thể.
  • COMMAND: Đây là lệnh chính mà Docker sẽ thực thi, chẳng hạn như run, ps, build, stop, v.v.
  • ARGUMENTS: Các đối số sẽ xác định thêm chi tiết cho lệnh, ví dụ như tên image, ID container, hoặc các tệp cấu hình.

Để xem danh sách đầy đủ các subcommands (lệnh con) mà Docker hỗ trợ, bạn có thể chạy lệnh sau:

docker --help

Output  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Để xem các tùy chọn có sẵn cho một lệnh cụ thể, hãy nhập:

docker docker-subcommand --help

Để xem thông tin toàn hệ thống về Docker, hãy sử dụng:

docker info

Hãy cùng khám phá một số lệnh này. Chúng ta sẽ bắt đầu từ việc làm việc với Docker images. Images trong Docker là các bản sao chỉ đọc (read-only) của một môi trường chứa phần mềm và các tệp cần thiết để chạy một ứng dụng trong container.

Bước 4: Làm Việc Với Docker Images

Trong bước này, chúng ta sẽ tìm hiểu chi tiết hơn về cách làm việc với Docker images. Docker images là cơ sở để tạo ra các container, và bạn sẽ cần hiểu cách quản lý chúng để tối ưu hóa quá trình phát triển và triển khai ứng dụng.

Docker containers được xây dựng từ Docker images. Mặc định, Docker sẽ tải các images này từ Docker Hub, một registry Docker được quản lý bởi Docker, công ty đứng sau dự án Docker. Docker Hub là nơi lưu trữ chính thức các Docker images và là một nguồn tài nguyên phong phú cho nhiều ứng dụng và hệ điều hành Linux.

Điều đặc biệt về Docker Hub là bất kỳ ai cũng có thể lưu trữ Docker images của mình trên đó, giúp chia sẻ với cộng đồng hoặc giữa các nhóm phát triển. Chính vì vậy, hầu hết các ứng dụng phổ biến và các bản phân phối Linux mà bạn cần sử dụng đều có sẵn dưới dạng Docker images trên Docker Hub.

Để kiểm tra xem bạn có thể truy cập và tải Docker images từ Docker Hub hay không, bạn có thể chạy lệnh sau:

docker run hello-world

OutputUnable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:bfea6278a0a267fad2634554f4f0c6f31981eea41c553fdf5a83e95a41d40c38
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

...

Khi Docker không thể tìm thấy image hello-world trên máy tính của bạn, nó đã tự động tải image này từ Docker Hub, là kho lưu trữ mặc định của Docker. Docker Hub là nơi chứa hàng triệu Docker images, từ các ứng dụng phổ biến đến các hệ điều hành, giúp bạn dễ dàng tải và sử dụng chúng.

Sau khi image được tải về, Docker tiếp tục tạo một container từ image đó và chạy ứng dụng bên trong container. Ứng dụng này sau đó hiển thị thông điệp xác nhận rằng Docker đã được cài đặt và hoạt động bình thường. Bạn có thể tìm kiếm hình ảnh có sẵn trên Docker Hub bằng cách sử dụng lệnh docker với lệnh con search. Ví dụ, để tìm kiếm hình ảnh Ubuntu, hãy nhập:

docker search ubuntu

Tập lệnh sẽ thu thập Docker Hub và trả về danh sách tất cả các hình ảnh có tên khớp với chuỗi tìm kiếm. Trong trường hợp này, đầu ra sẽ tương tự như sau:

OutputNAME                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
			ubuntu                           Ubuntu is a Debian-based Linux operating sys…   14048     [OK]
			websphere-liberty                WebSphere Liberty multi-architecture images …   283       [OK]
			ubuntu-upstart                   DEPRECATED, as is Upstart (find other proces…   112       [OK]
			neurodebian                      NeuroDebian provides neuroscience research s…   88        [OK]
			open-liberty                     Open Liberty multi-architecture images based…   51        [OK]
			...

Trong cột OFFICIAL, một ký hiệu OK cho thấy đây là một image được xây dựng và hỗ trợ bởi công ty đứng sau dự án. Những images này thường được đảm bảo về chất lượng và độ tin cậy, vì chúng được duy trì và cập nhật thường xuyên. Khi bạn đã xác định được image mà mình muốn sử dụng, bạn có thể tải nó về máy tính của mình bằng cách sử dụng lệnh docker pull. Ví dụ, để tải image Ubuntu, bạn chỉ cần chạy:

docker pull ubuntu

OutputUsing default tag: latest
latest: Pulling from library/ubuntu
e0b25ef51634: Pull complete
Digest: sha256:9101220a875cee98b016668342c489ff0674f247f6ca20dfc91b91c0f28581ae
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

Khi một Docker image đã được tải về, bạn có thể sử dụng lệnh docker run để tạo và chạy một container từ image đó. Như bạn đã thấy trong ví dụ với hello-world, nếu Docker không tìm thấy image trên máy tính của bạn khi bạn sử dụng lệnh docker run, Docker sẽ tự động tải image từ Docker Hub trước khi tạo container và chạy nó. Để xem những hình ảnh đã được tải xuống máy tính của bạn, hãy nhập:

docker images

OutputREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              1d622ef86b13        3 weeks ago         73.9MB
hello-world         latest              bf756fb1ae65        4 months ago        13.3kB

Như bạn sẽ thấy trong phần sau của hướng dẫn này, các Docker images mà bạn sử dụng để chạy containers có thể được chỉnh sửa và sử dụng để tạo ra những Docker images mới. Quá trình này cho phép bạn tùy chỉnh container của mình, thêm vào các phần mềm, cấu hình, hoặc tệp cần thiết, rồi từ đó tạo một image mới.

Sau khi đã tạo được một image mới, bạn có thể tải (hay “push” theo thuật ngữ kỹ thuật) image này lên Docker Hub hoặc các Docker registry khác để chia sẻ với người khác hoặc sử dụng lại trên các máy chủ khác. Quá trình tạo và push một image giúp bạn dễ dàng tái sử dụng và triển khai các container tương tự trên các môi trường khác nhau mà không cần phải cấu hình lại mọi thứ từ đầu.

Bước 5: Chạy Docker Container

Ở bước trên, bạn đã chạy một container hello-world, đây chỉ là một ví dụ đơn giản nhằm xác nhận rằng Docker đang hoạt động đúng. Container này chạy một lần, in ra thông báo kiểm tra và sau đó tự động thoát. Mặc dù hữu ích trong việc kiểm tra ban đầu, nhưng container thực tế có thể mạnh mẽ hơn rất nhiều.

Trên thực tế, Docker containers có thể duy trì trạng thái hoạt động, chạy các ứng dụng nền (background services), hoặc thậm chí cung cấp một môi trường tương tác giống như cách bạn làm việc với một máy ảo. Tuy nhiên, điểm đặc biệt là container nhẹ hơn rất nhiều so với máy ảo truyền thống, sử dụng ít tài nguyên hơn và khởi động gần như tức thì.

Chúng ta sẽ cùng khám phá cách khởi tạo một container có thể tương tác, nơi bạn có thể gõ lệnh và thao tác trực tiếp bên trong môi trường đó tương tự như khi bạn SSH vào một máy chủ Linux thực thụ.

Bây giờ, hãy cùng thử chạy một container tương tác bằng cách sử dụng image Ubuntu mới nhất. Khi kết hợp hai tùy chọn -i-t, bạn sẽ có quyền truy cập vào shell bên trong container.

docker run -it ubuntu

  • Giải thích
    • i (interactive): giữ cho kết nối đầu vào (stdin) mở, cho phép bạn nhập lệnh vào container.
    • t (tty): cấp cho bạn một terminal ảo bên trong container.

Khi chạy lệnh này, bạn sẽ thấy dấu nhắc shell giống như đang sử dụng một phiên bản Ubuntu thực thụ. Tại đây, bạn có thể cài đặt phần mềm, thay đổi file, hoặc làm bất kỳ điều gì bạn vẫn làm với một máy Linux thông thường.

Output
root@d9b100f2f636:/#

Trong trường hợp này, d9b100f2f636 là ID của container đang chạy. Đây là một mã định danh duy nhất mà Docker gán cho container, giúp bạn dễ dàng theo dõi và quản lý nó sau này.

Khi đã vào bên trong container, bạn có thể chạy bất kỳ lệnh nào giống như đang thao tác trên một máy chủ Ubuntu thực thụ. Một điểm tiện lợi là bạn không cần dùng sudo, vì mặc định bạn đang hoạt động với quyền root trong container.

Ví dụ, để cập nhật danh sách gói phần mềm bên trong container, chỉ cần chạy:

root@d9b100f2f636:/# apt update

Sau đó cài đặt bất kỳ ứng dụng nào vào đó. Hãy cài đặt Node.js:

root@d9b100f2f636:/# apt install nodejs

Lệnh trên cài đặt Node.js trong container từ kho lưu trữ Ubuntu chính thức. Khi quá trình cài đặt hoàn tất, hãy xác minh rằng Node.js đã được cài đặt:

root@d9b100f2f636:/# node -v

Output
v12.22.9

Một điều quan trọng cần ghi nhớ khi làm việc với Docker container là: mọi thay đổi bạn thực hiện bên trong container chỉ ảnh hưởng đến chính container đó.

Điều này có nghĩa là:

  • Nếu bạn cài đặt phần mềm, sửa file cấu hình, hoặc tạo thư mục mới trong container thì tất cả các thay đổi đó sẽ không ảnh hưởng đến hệ thống máy chủ đang chạy Docker.
  • Mỗi container giống như một môi trường tách biệt, độc lập hoàn toàn với hệ điều hành chính.

Vì tính chất cô lập này, bạn có thể tự tin thử nghiệm, thay đổi và thậm chí phá hỏng mọi thứ bên trong container mà không lo làm hỏng hệ thống thật. Nếu container gặp sự cố, bạn chỉ cần xóa nó và tạo mới lại từ image ban đầu là xong.

Sau khi bạn đã hoàn tất các thao tác bên trong container, bạn có thể dễ dàng thoát ra và quay lại hệ thống máy chủ chính bằng cách gõ:

exit

Bây giờ, chúng ta đã biết cách tạo và làm việc bên trong một container, chúng ta hãy cùng khám phá cách quản lý các container đang hoạt động hoặc đã dừng trên hệ thống.

Bước 6: Quản Lý Docker Containers

Sau một thời gian sử dụng Docker, hệ thống của bạn có thể sẽ có rất nhiều container, bao gồm cả container đang chạy và container đã dừng. Để kiểm tra các container đang hoạt động, bạn chỉ cần sử dụng lệnh sau:

docker ps

Bạn sẽ thấy kết quả tương tự như sau:

Output
CONTAINER ID        IMAGE               COMMAND             CREATED

Trong quá trình thực hành ở bài hướng dẫn này, bạn đã khởi tạo hai container: một từ image hello-world và một từ image ubuntu. Mặc dù cả hai container này đã dừng hoạt động, nhưng chúng vẫn còn tồn tại trên hệ thống của bạn. Để xem danh sách tất cả container bao gồm cả những container đã thoát, bạn dùng lệnh sau:

docker ps -a

OutputCONTAINER ID   IMAGE         COMMAND   CREATED         STATUS                     PORTS     NAMES
1c08a7a0d0e4   ubuntu        "bash"     About a minute ago   Exited (0) 7 seconds ago             dazzling_taussig
587000e49d53   hello-world   "/hello"   5 minutes ago        Exited (0) 5 minutes ago             adoring_kowalevski

Để xem container mới nhất bạn đã tạo, hãy truyền lệnh -l vào đó:

docker ps -l

Output
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS                     PORTS     NAMES
1c08a7a0d0e4   ubuntu    "bash"    3 minutes ago   Exited (0) 2 minutes ago             dazzling_taussig

Khi một container đã dừng, bạn không cần tạo lại từ đầu. Bạn hoàn toàn có thể khởi động lại container đó bằng lệnh docker start, theo sau là ID hoặc tên của container.

Ví dụ, để khởi động lại container Ubuntu có ID là 1c08a7a0d0e4, bạn chỉ cần chạy lệnh sau:

docker start 1c08a7a0d0e4

Container sẽ khởi động và bạn có thể sử dụng docker ps để xem trạng thái của nó:

Output
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
1c08a7a0d0e4   ubuntu    "bash"    6 minutes ago   Up 8 seconds             dazzling_taussig

Khi bạn không còn cần container hoạt động nữa, bạn có thể dừng nó lại bằng lệnh:

docker stop <container_id_or_name>

Thay vì sử dụng Container ID, bạn cũng có thể dùng tên container là tên mà Docker tự động gán nếu bạn không chỉ định lúc tạo. Trong ví dụ này, container có tên là dazzling_taussig, vì vậy bạn có thể dừng nó bằng lệnh:

docker stop dazzling_taussig

Khi bạn đã xác định rằng một container không còn cần thiết nữa, bạn có thể xóa nó khỏi hệ thống bằng lệnh:

docker rm <container_id_or_name>

Có 1 mẹo nhỏ khi bạn khởi chạy một container mới bằng lệnh docker run đó là bạn có thể chủ động đặt tên cho container thay vì để Docker tự sinh tên ngẫu nhiên. Điều này giúp dễ quản lý và thao tác sau này. Sử dụng tuỳ chọn --name, cú pháp như sau:

docker run --name my_ubuntu_container ubuntu

Ngoài ra, nếu chỉ cần chạy container tạm thời (ví dụ như để test hoặc chạy một tác vụ ngắn hạn), bạn có thể dùng tuỳ chọn --rm. Tùy chọn này sẽ đảm bảo container tự động xóa sau khi dừng, giúp hệ thống của bạn không bị lộn xộn bởi các container không còn dùng đến:

docker run --rm ubuntu

Một trong những tính năng mạnh mẽ của Docker là khả năng biến container thành image, từ đó bạn có thể dùng để tạo ra các container mới với cùng trạng thái, cấu hình và dữ liệu. Chúng ta cùng đi tìm hiểu ở bước sau.

Bước 7: Commit Container Docker Thành Image

Khi bạn làm việc với một Docker container tạo file mới, chỉnh sửa cấu hình, cài đặt phần mềm tất cả các thay đổi này chỉ tồn tại bên trong container đó. Bạn có thể tạm dừng container, khởi động lại nó, và các thay đổi vẫn được giữ nguyên. Tuy nhiên, nếu bạn xóa container bằng lệnh:

docker rm <container_id_or_name>

thì toàn bộ thay đổi sẽ biến mất vĩnh viễn. Để tránh mất công làm lại, bạn có thể lưu lại trạng thái hiện tại của container bằng cách commit nó thành một image mới. Điều này tương tự như tạo một snapshot cho máy ảo.

docker commit my_temp_container my_saved_image

Sau đó, bạn có thể tạo các container mới dựa trên image đó bất cứ lúc nào, mang lại sự linh hoạt và khả năng tái sử dụng cho quá trình phát triển và triển khai ứng dụng.

Sau khi đã tạo một Docker image từ container của bạn, bước tiếp theo là chia sẻ nó với người khác. Điều này cho phép đồng đội, cộng đồng hoặc các hệ thống khác có thể dễ dàng tạo container từ image bạn đã cấu hình sẵn.

Bước 8: Đẩy hình ảnh Docker vào kho lưu trữ Docker

Bạn có một image tùy chỉnh từ container, bước tiếp theo hợp lý là chia sẻ nó, có thể chỉ với một vài người bạn, hoặc công khai với cả thế giới qua Docker Hub hay một Docker registry riêng mà bạn đang sử dụng. Để đẩy hình ảnh lên Docker Hub hoặc Docker registry nào khác, bạn phải có tài khoản ở đó. Để đẩy hình ảnh của bạn, trước tiên hãy đăng nhập vào Docker Hub.

docker login -u docker-registry-username

Lưu ý: Nếu tên người dùng trên Docker Registry (ví dụ: Docker Hub) khác với username cục bộ bạn dùng để tạo image, bạn phải tag lại image với tên tài khoản registry trước khi thực hiện đẩy image lên.

Ví dụ: Giả sử bạn tạo image cục bộ dưới tên sammy, nhưng tài khoản Docker Hub của bạn là dockerhubuser, bạn cần tag lại như sau:

docker tag ubuntu-nodejs dockerhubuser/ubuntu-nodejs

Lúc này, bạn có thể đẩy image đã tag lên Docker Hub bằng lệnh:

docker push dockerhubuser/ubuntu-nodejs

Trong bài thực hành username local là sammy cũng với user docker hub nên chúng ta chỉ cần thực hiện câu lệnh sau để đẩy image.

docker push sammy/ubuntu-nodejs

Quá trình này có thể mất một thời gian để hoàn tất khi tải hình ảnh lên, nhưng khi hoàn tất, đầu ra sẽ như thế này:

OutputThe push refers to a repository [docker.io/sammy/ubuntu-nodejs]
e3fbbfb44187: Pushed
5f70bf18a086: Pushed
a3b5c80a4eba: Pushed
7f18b442972b: Pushed
3ce512daaf78: Pushed
7aae4540b42d: Pushed

...

Sau khi bạn đã đẩy image lên Docker Hub (hoặc một registry khác), bạn có thể dễ dàng tải image đó xuống bất kỳ máy nào khác có Docker được cài đặt.

docker pull sammy/ubuntu-nodejs

Tiếp theo nếu bạn đang phát triển hoặc triển khai các ứng dụng đòi hỏi hiệu suất tính toán cao như trí tuệ nhân tạo (AI), học sâu (deep learning) hoặc xử lý ảnh/video, thì việc sử dụng GPU trong container Docker là một lợi thế cực kỳ lớn. Thay vì chỉ dựa vào CPU, bạn có thể tận dụng toàn bộ sức mạnh phần cứng GPU để tăng tốc quá trình huấn luyện mô hình, inference, hoặc tính toán ma trận khối lượng lớn.

Cài đặt Docker với hỗ trợ GPU

Để cài Docker với GPU support, bạn sẽ cần thực hiện quy trình hơi khác so với việc cài đặt Docker thông thường. Lý do là vì việc sử dụng GPU trong container đòi hỏi thêm driver, runtime và một số cấu hình bổ sung để Docker có thể giao tiếp với tài nguyên GPU của máy chủ. Dưới đây là các bước chi tiết giúp bạn thiết lập Docker với GPU support trên hệ điều hành Ubuntu:

Bước 1: Cài Đặt NVIDIA Driver

Docker sử dụng GPU thông qua NVIDIA driver đã được cài đặt sẵn trên hệ thống. Do đó, trước tiên bạn cần đảm bảo đã cài đúng phiên bản driver phù hợp cho GPU của bạn.

Bạn có thể kiểm tra driver hiện tại bằng lệnh:

nvidia-smi

Nếu chưa cài driver, bạn có thể cài thông qua lệnh:

sudo apt install nvidia-driver-525
sudo reboot

*Lưu ý: Thay số 525 bằng phiên bản driver mới nhất tương thích với GPU của bạn. Bạn có thể tìm thấy hướng dẫn cài đặt trên trang web NVIDIA. https://www.nvidia.com/en-us/drivers/.*

Bước 2: Cài Đặt NVIDIA Container Toolkit

NVIDIA Container Toolkit là công cụ giúp Docker container truy cập GPU. Làm theo các bước sau để cài đặt:

# Thiết lập biến môi trường
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)

# Thêm GPG key
curl -s -L <https://nvidia.github.io/nvidia-docker/gpgkey> | \\
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-docker.gpg

# Thêm repository cho NVIDIA Docker
curl -s -L <https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list> | \\
  sed 's#https://#deb [signed-by=/usr/share/keyrings/nvidia-docker.gpg] https://#' | \\
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list

# Cập nhật hệ thống và cài nvidia-docker2
sudo apt update
sudo apt install -y nvidia-docker2

# Khởi động lại Docker daemon
sudo systemctl restart docker

Bước 3: Kiểm Tra GPU Trong Container

Sau khi hoàn tất cài đặt, bạn hãy chạy container thử nghiệm để xác minh GPU đã hoạt động:

docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi

Nếu lệnh này trả về thông tin GPU như tên card, bộ nhớ, trạng thái driver, thì bạn đã cài đặt thành công Docker với GPU support. Để biết thêm thông tin về cách cài đặt và sử dụng Docker có hỗ trợ GPU, hãy tham khảo các tài nguyên sau:

Khi triển khai Docker trong môi trường thực tế đặc biệt là môi trường production, bảo mật phải là một ưu tiên hàng đầu. Mặc dù Docker mang lại sự tiện lợi và linh hoạt trong việc quản lý ứng dụng, nhưng nếu không được cấu hình đúng cách, nó có thể trở thành điểm yếu nghiêm trọng trong hệ thống của bạn. Chúng ta sẽ cùng tìm hiểu những thực tiễn bảo mật tốt nhất để bảo vệ hệ thống Docker, hạn chế các nguy cơ từ bên trong và bên ngoài.

Những Thực Tiễn Bảo Mật Cần Thiết Khi Triển Khai Docker

Bảo mật Docker Engine rất quan trọng để đảm bảo rằng các container và hệ thống máy chủ của bạn được bảo vệ khỏi các lỗ hổng tiềm ẩn. Sau đây là một số biện pháp thực hành tốt nhất cần tuân theo:

Sử dụng nguyên tắc quyền tối thiểu:

  • Nguyên tắc đặc quyền tối thiểu (Least Privilege) có nghĩa là container chỉ nên được cấp những quyền tối thiểu cần thiết để thực hiện nhiệm vụ của nó. Điều này giúp giảm khả năng container bị lợi dụng để thực hiện các hành động độc hại trên hệ thống.

Chạy container với user không phải root

  • Mặc định, Docker chạy container với quyền root bên trong. Đây là một lỗ hổng bảo mật tiềm ẩn nếu container bị khai thác.

Cập nhật Docker thường xuyên

  • Một trong những cách đơn giản nhất để giữ an toàn là đảm bảo Docker Engine luôn được cập nhật phiên bản mới nhất.

Kích hoạt Docker Content Trust (DCT)

  • Docker Content Trust cho phép xác minh tính toàn vẹn của image thông qua chữ ký số. Điều này đảm bảo image bạn kéo về là hợp lệ, không bị thay đổi hoặc giả mạo.

Hạn chế mở cổng mạng không cần thiết

  • Việc mở quá nhiều port khi chạy container là điều không nên. Hãy chỉ expose đúng port cần thiết.

Bây giờ bạn làm việc với nhiều container, việc quản lý từng container một bằng tay sẽ trở nên phức tạp và tốn thời gian. Đây là lúc Docker Compose phát huy tác dụng. Nó cho phép bạn định nghĩa, cấu hình và chạy nhiều container chỉ với một file cấu hình duy nhất.

Sử dụng Docker Compose

Docker Compose giúp đơn giản hóa việc triển khai và quản lý các ứng dụng phức tạp bao gồm nhiều container. Dưới đây là một số lợi ích nổi bật:

Dễ Dàng Định Nghĩa Ứng Dụng

Bạn có thể định nghĩa toàn bộ kiến trúc ứng dụng chỉ trong một file YAML (docker-compose.yml). Trong file này, bạn có thể khai báo:

  • Các dịch vụ cần thiết (ví dụ: web, database, cache…).
  • Volume cho dữ liệu.
  • Mạng riêng giữa các container.
  • Biến môi trường và tham số khởi tạo.

Tự Động Hóa Việc Khởi Động

Chỉ với một lệnh đơn giản:

docker compose up

Toàn bộ hệ thống container sẽ được khởi động đồng bộ và đúng thứ tự phụ thuộc.

Quản Lý Nhiều Môi Trường

Bạn có thể dùng cùng một file docker-compose.yml cho nhiều môi trường (development, staging, production), chỉ cần tùy chỉnh biến môi trường hoặc override qua file docker-compose.override.yml.

Dễ Dàng Bảo Trì và Mở Rộng

Vì cấu trúc file Compose rõ ràng, bạn dễ dàng thêm dịch vụ mới, thay đổi cấu hình, hoặc cập nhật phiên bản container chỉ bằng cách chỉnh sửa YAML và chạy lại.

Hỗ Trợ Cho CI/CD

Docker Compose rất phù hợp để tích hợp vào các quy trình CI/CD, nhờ khả năng tái tạo nhanh môi trường ứng dụng giống nhau trên nhiều máy khác nhau (local, test, cloud…).

Sau một thời gian sử dụng, bạn có thể muốn gỡ bỏ Docker khỏi hệ thống vì nhiều lý do: dọn dẹp môi trường phát triển, cài đặt lại từ đầu hoặc chuyển sang môi trường khác.

Gỡ Cài Đặt Docker Trên Ubuntu

Xóa các gói Docker là một phần thiết yếu trong việc duy trì hệ thống của bạn và đảm bảo rằng bạn đã cài đặt phiên bản Docker mới nhất. Sau đây là một số bước cần thực hiện:

Bước 1: Gỡ Bỏ Các Gói Docker

Chạy lệnh sau để gỡ toàn bộ các gói liên quan đến Docker:

sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Lệnh purge sẽ xóa cả gói lẫn các file cấu hình liên quan.

Bước 2: Xóa Dữ Liệu Docker Còn Lưu Trữ

Mặc dù bạn đã gỡ các gói, dữ liệu Docker (container, images, volumes…) vẫn còn nằm trong hệ thống. Để xóa sạch, hãy chạy:

sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

Lưu ý: Hành động này là không thể khôi phục, nên hãy đảm bảo bạn đã sao lưu dữ liệu nếu cần.

Bước 3: Kiểm Tra Docker Đã Được Gỡ Thành Công

Bạn có thể xác minh bằng cách chạy:

docker --version

Nếu hệ thống trả về thông báo lỗi kiểu như "command not found", nghĩa là Docker đã được gỡ bỏ hoàn toàn. Vậy là bạn đã hoàn tất việc dọn dẹp Docker khỏi hệ thống.

Qua các phần trên, chúng ta đã cùng nhau khám phá gần như toàn bộ hành trình làm việc với Docker từ quá trình cài đặt, sử dụng lệnh cơ bản, quản lý container và image, cho đến các chủ đề nâng cao như Docker Compose, GPU support và các thực hành bảo mật. Việc làm chủ Docker không chỉ giúp bạn triển khai ứng dụng nhanh chóng và linh hoạt hơn mà còn mở ra cánh cửa để tiếp cận các mô hình triển khai hiện đại như microservices hay CI/CD pipelines.

Tổng kết

Sau hành trình khám phá Docker từ cơ bản đến nâng cao, bạn đã nắm trong tay những kiến thức nền tảng vững chắc để làm chủ công cụ container mạnh mẽ này. Từ việc cài đặt Docker trên Ubuntu, thao tác với container và image, đến sử dụng Docker Compose để triển khai ứng dụng đa thành phần mỗi bước đều giúp bạn tiến gần hơn đến một quy trình phát triển phần mềm hiện đại và linh hoạt. Bên cạnh đó, bạn cũng đã tìm hiểu cách bật hỗ trợ GPU để phục vụ các tác vụ tính toán chuyên sâu, áp dụng các thực hành bảo mật để bảo vệ hệ thống, và biết cách dọn dẹp Docker khi không còn sử dụng. Docker không chỉ giúp đơn giản hóa việc phát triển và triển khai ứng dụng mà còn là nền tảng để bạn tiến xa hơn với CI/CD, DevSecOps và Kubernetes. Nếu bạn đã đọc đến đây, xin chúc mừng bạn đã sẵn sàng ứng dụng Docker vào các dự án thực tế. Hãy tiếp tục tìm hiểu về Dockerfile nâng cao, triển khai CI/CD pipelines, hoặc mở rộng sang Kubernetes để nâng tầm kỹ năng của mình.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.