Tổng hợp lệnh Docker Compose thường dùng trên server
Tổng hợp các lệnh Docker Compose V2 thiết yếu cho quản trị server. Hướng dẫn cách quản lý vòng đời container, xem log, xử lý network và dọn dẹp hệ thống an toàn mà không gây lỗi.
Các lệnh Compose bạn thực sự cần dùng
Docker Compose phát hành hơn bốn mươi lệnh con. Công việc hàng ngày trên server chỉ dùng khoảng một tá lệnh. Trang này nhóm các lệnh đó theo tác vụ bạn đang thực hiện, đưa ra một lý do đơn giản cho mỗi lệnh và dẫn đến bài phân tích chuyên sâu khi một lệnh tiềm ẩn bẫy lỗi.
Mọi thứ ở đây đều sử dụng Compose V2: docker compose có dấu cách, không phải script docker-compose cũ. V2 là một plugin Go được cài đặt cùng với Docker Engine, và V1 đã bị loại bỏ khỏi các gói hiện tại, vì vậy việc chạy docker-compose: command not found trên một máy Ubuntu mới tính đến tháng 7 năm 2026 là điều bình thường chứ không phải lỗi. Kiểm tra bằng docker compose version. Nếu lệnh đó không in ra gì, hãy cài đặt gói docker-compose-plugin.
Mọi lệnh dưới đây đều chạy từ thư mục chứa compose.yaml của bạn, vì Compose lấy tên dự án từ thư mục đó và tìm file dựa trên đường dẫn tương đối. Chạy cùng lệnh đó ở cấp thư mục cao hơn và Compose sẽ dừng lại với no configuration file provided: not found. Nếu định dạng file còn mới với bạn, hãy bắt đầu với file Compose đầu tiên trên VPS và quay lại đây để xem các lệnh.
Vòng đời: bốn lệnh bạn cần biết và lệnh xóa container
docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose downup -d tạo network, tạo các container, khởi động chúng và trả về kết quả. Nó trả về ngay khi các container được tạo xong, đó là lý do tại sao một script triển khai chạy ngay sau đó bằng lệnh curl thường thất bại ở lần thử đầu tiên. up -d --wait sẽ chặn cho đến khi mọi service có khai báo healthcheck báo trạng thái healthy, và thoát với mã lỗi khác không nếu có service nào không đạt trạng thái đó. Cờ này chỉ hiệu quả khi healthcheck được thiết lập đúng, vì vậy hãy viết một healthcheck mà Compose có thể tin tưởng trước khi sử dụng nó trong tự động hóa.
stop dừng các container và giữ lại chúng, vì vậy start sẽ khởi động lại chính các container đó với cùng lớp ghi (writable layer). down dừng và sau đó xóa các container cùng với network của dự án. Mọi dữ liệu được ghi bên trong container mà không nằm trong volume sẽ bị mất. Đây là hiểu lầm phổ biến và gây hậu quả lớn nhất trong Compose, và sự khác biệt đầy đủ giữa down và stop sẽ giải thích rõ những rủi ro này.
restart không phải là lệnh reload. Nó dừng và khởi động lại chính container đó với cấu hình hiện tại, vì vậy một biến môi trường thay đổi, một image tag mới hoặc một port mapping được chỉnh sửa sẽ không có tác dụng gì cả. Để áp dụng thay đổi file, bạn cần chạy lại up -d. Compose sẽ so sánh từng service với container đang chạy và chỉ tạo lại những service có cấu hình đã thay đổi.
Áp dụng thay đổi: recreate, pull, hoặc rebuild
docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build webup -d khi chạy độc lập sẽ không thực hiện gì nếu không có thay đổi, đó là lý do lệnh này an toàn để chạy nhiều lần. --force-recreate ghi đè lên cơ chế so sánh đó và thay thế mọi container ngay cả khi cấu hình giống hệt nhau, vì vậy đây là cách nhanh nhất để xóa trạng thái bất thường bên trong container.
Việc cập nhật image cần hai lệnh vì chúng thực hiện hai việc khác nhau. pull tải xuống image hiện tại cho mỗi tag được liệt kê trong file. Sau đó, up -d nhận thấy ID image của service không còn khớp với container đang chạy và sẽ recreate nó. Nếu bỏ qua bước pull, up -d sẽ tiếp tục chạy latest của tháng trước mà không báo lỗi.
build áp dụng cho các service khai báo phần build: thay vì image:. up -d --build thực hiện build và khởi động trong một bước, đây là vòng lặp thông thường khi bạn đang thay đổi code. Chỉ dùng đến --no-cache khi một layer trong cache rõ ràng đã cũ, vì lệnh này sẽ build lại mọi layer từ đầu.
Xem các tiến trình đang chạy
docker compose ps
docker compose ps -a
docker compose logs -f --tail=100
docker compose logs --since 15m --timestamps db
docker compose top
docker compose lsps chỉ liệt kê các container đang chạy. Một service bị crash trong quá trình khởi động sẽ không hiển thị ở đó trừ khi bạn thêm -a, vì vậy việc một container không xuất hiện trong ps trong khi ps -a hiển thị nó là Exited (1) là trạng thái bình thường của một lỗi khởi động. Hãy đọc mã thoát (exit code), sau đó đọc các log.
logs -f theo dõi mọi service cùng một lúc và thêm tên service vào đầu mỗi dòng, đây là chế độ xem bạn cần khi các service giao tiếp với nhau và thứ tự sự kiện là quan trọng. Hãy chỉ định tên service để thu hẹp phạm vi. --tail=100 rất quan trọng đối với một container đã chạy được một tháng, vì mặc định nó sẽ in toàn bộ lịch sử và làm tràn terminal. --since 15m trả lời câu hỏi mà bạn thường gặp, đó là điều gì đã xảy ra trong lần khởi động lại mà bạn vừa thực hiện.
top liệt kê các tiến trình bên trong mỗi container, giúp phân biệt giữa "container đang chạy" và "tiến trình bên trong nó đang chạy". ls thoát ra khỏi thư mục hiện tại và liệt kê mọi dự án Compose trên host cùng với trạng thái của chúng, để bạn có thể tìm thấy stack mà bạn đã khởi chạy từ ba tháng trước.
Truy cập shell bên trong một service
docker compose exec web sh
docker compose exec -u root web sh
docker compose run --rm web env
docker compose run --rm --no-deps web shexec chạy một lệnh bên trong container đang hoạt động. run khởi chạy một container mới từ cùng định nghĩa service, đây là cách bạn cần dùng khi service không chạy đủ lâu để thực hiện lệnh exec. Luôn kết hợp run với --rm, vì nếu không, mỗi lần gọi lệnh sẽ để lại một container đã dừng, và chúng sẽ tích tụ cho đến khi docker compose ps -a trở nên không thể đọc được.
Hãy thử sh trước bash. Các image dựa trên Alpine không chứa bash, và lỗi sẽ hiển thị là exec: "bash": executable file not found in $PATH. Việc thêm --no-deps vào run sẽ bỏ qua các phụ thuộc của service, giúp ngăn chặn việc kiểm tra cấu hình nhanh làm khởi động toàn bộ database của bạn.
run --rm web env là cách nhanh nhất để xem môi trường thực tế mà một service nhận được, sau khi mọi file .env, khối environment: và biến shell đã được hợp nhất. Khi một giá trị bị sai, thứ tự hợp nhất thường là nguyên nhân, và cách Compose giải quyết các file env và secret sẽ làm rõ nguồn nào được ưu tiên.
Mạng, cổng và phân giải tên miền
docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networksCompose đặt mọi service vào một mạng dự án, và mỗi tên service là một tên DNS trên mạng đó. Chạy getent hosts db bên trong web sẽ in ra IP của container khi việc phân giải hoạt động và không in gì cả khi nó không hoạt động, vì vậy nó trả lời câu hỏi "các container này có thấy nhau không" trong hai giây. Nếu tên miền phân giải được nhưng kết nối bị từ chối, tiến trình bên trong db đang bind vào 127.0.0.1 thay vì 0.0.0.0, nên nó không bao giờ chấp nhận gói tin từ container khác. Phần còn lại của mô hình đó nằm trong cách mạng Compose và DNS service hoạt động.
port web 80 in ra địa chỉ host và cổng mà một cổng container được publish, giúp tránh việc phải đoán khi mapping đến từ một biến. Việc publish một cổng cũng ghi một quy tắc firewall mà Docker tự quản lý, và quy tắc đó nằm trước quy tắc của bạn, vì vậy một service mà bạn tin là riêng tư có thể bị mở ra internet. Trường hợp đó được đề cập trong tại sao các cổng Docker được publish lại bỏ qua ufw.
Volumes và dữ liệu
docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -vconfig --volumes liệt kê các named volume mà project khai báo, mỗi volume trên một dòng. Bạn cần sao lưu danh sách đó. cp sao chép tệp vào hoặc ra khỏi container mà không cần mở shell, bằng cách sử dụng định dạng service:path ở phía container.
down -v xóa các named volume đó cùng với các container. Đây là lệnh phù hợp để gỡ bỏ một test stack, nhưng là lệnh sai lầm đối với bất kỳ dữ liệu nào quan trọng, vì lệnh này không yêu cầu xác nhận và không thể hoàn tác. Bind mount vẫn tồn tại sau khi chạy lệnh này vì chúng nằm trên filesystem của host. Sự khác biệt về phạm vi ảnh hưởng này là một lý do để bạn cân nhắc kỹ lưỡng khi chọn giữa bind mount và named volume.
Dọn dẹp giải phóng dung lượng đĩa mà không mất dữ liệu
docker compose down --remove-orphans
docker system df
docker image prune -a
docker builder prune--remove-orphans xóa các container thuộc về dự án nhưng không còn xuất hiện trong file, đây chính xác là kết quả sau khi bạn đổi tên một service. Nếu không có lệnh này, các container đó vẫn tiếp tục chạy và không hiển thị với docker compose ps.
docker system df hiển thị nơi dung lượng đĩa đang bị chiếm dụng trước khi bạn xóa bất cứ thứ gì, phân tách rõ ràng giữa image, container, volume cục bộ và build cache cùng với dung lượng có thể thu hồi cho từng mục. image prune -a xóa mọi image không có tag nào trỏ tới, và trên một máy chủ đã pull nhiều phiên bản của một image lớn, đây thường là cách giải phóng dung lượng hiệu quả nhất. builder prune xóa build cache, thứ vốn âm thầm tăng dung lượng trên bất kỳ server nào tự build image của riêng mình.
Không lệnh nào trong số đó tác động đến named volume. Chỉ có docker volume prune và docker compose down -v mới làm điều đó.
Kiểm tra file trước khi gây lỗi
docker compose config --quiet
docker compose config --services
docker compose --dry-run up -dconfig --quiet kiểm tra và không in ra gì nếu thành công, vì vậy nó phù hợp trong bước tiền triển khai hoặc git hook. Lệnh config cơ bản in ra file đã được gộp và nội suy hoàn toàn, đây là cách bạn xác nhận một biến đã được giải quyết và file ghi đè đã được xếp lớp đúng như mong đợi. Một biến chưa được thiết lập sẽ xuất hiện ở đó dưới dạng giá trị trống, bên cạnh cảnh báo The "X" variable is not set. Defaulting to a blank string.
--dry-run là một flag toàn cục thay vì flag của subcommand, vì vậy nó nằm trước up. Nó in ra mọi hành động mà Compose sẽ thực hiện và không thay đổi bất cứ điều gì, đây là ba mươi giây xứng đáng trước khi thực hiện down trên một stack quan trọng.
Làm việc với nhiều tệp, cấu hình và dự án
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose --profile debug up -d
docker compose -p staging up -dNhiều cờ -f sẽ được gộp theo thứ tự, và các tệp phía sau sẽ ghi đè lên các tệp phía trước theo từng khóa. Đây là cách tiêu chuẩn để duy trì một tệp cơ sở với một tệp ghi đè nhỏ cho môi trường production, tuy nhiên các quy tắc sẽ khác nhau đối với danh sách và bản đồ, vì vậy hãy đọc cách Compose gộp nhiều tệp trước khi bạn gỡ lỗi một kết quả không mong muốn.
--profile khởi động các dịch vụ được gắn thẻ với cấu hình đó cùng với các dịch vụ không được gắn thẻ, giúp giữ cho các công cụ gỡ lỗi không xuất hiện trong một up thông thường. -p thiết lập tên dự án, vì vậy hai bản sao của một stack có thể chạy song song với các mạng riêng biệt và tên volume riêng biệt. Việc khôi phục stack sau khi khởi động lại không phải là một lệnh bạn nhập thủ công, mà là một unit tự chạy cho bạn, được mô tả trong khởi động các Compose stack khi khởi động hệ thống.
FAQ
Cái gì đã thay thế docker-compose bằng dấu gạch nối?
Compose V2, được gọi là docker compose với một khoảng trắng. Đây là một plugin đi kèm với Docker Engine, và công cụ Python V1 không còn được cài đặt bởi các gói hiện tại. Nếu lệnh có khoảng trắng không hiển thị gì, hãy cài đặt gói docker-compose-plugin cho bản phân phối của bạn. Hãy cập nhật các script cũ sang dạng có khoảng trắng thay vì thêm alias, vì V2 có các flag mà V1 không có.
Tại sao docker compose restart không nhận thay đổi cấu hình của tôi?
restart dừng và khởi động lại container hiện có với cấu hình lúc nó được tạo, và nó không bao giờ đọc lại compose.yaml. Bất kỳ thay đổi nào đối với biến môi trường, port, volume hoặc image tag đều cần docker compose up -d, lệnh này sẽ so sánh từng service với container đang chạy của nó và tạo lại những service có sự khác biệt. Thêm --force-recreate khi bạn muốn việc thay thế diễn ra ngay cả khi không có gì trong file thay đổi.
Làm thế nào để cập nhật một service lên image mới hơn?
Chạy docker compose pull, sau đó là docker compose up -d. Lệnh pull sẽ lấy image hiện tại cho mỗi tag trong file, và up -d sẽ tạo lại bất kỳ service nào có ID image không còn khớp với container của nó nữa. Chạy riêng up -d sẽ sử dụng lại image đã có trên ổ đĩa, đó là lý do tại sao một stack được ghim vào latest vẫn chạy trên bản build cũ nhiều tháng mà không báo lỗi.
Những lệnh dọn dẹp nào an toàn trên server đang chạy?
docker system df, docker image prune -a và docker builder prune chỉ xóa image và cache, vì vậy các service đang chạy vẫn hoạt động bình thường và các named volume không bị ảnh hưởng. Cặp lệnh nguy hiểm là docker compose down -v và docker volume prune, chúng xóa các named volume mà không cần xác nhận. Hãy chạy docker compose config --volumes trước để biết những gì có nguy cơ bị xóa.
Tôi có thể chạy một lệnh mà không cần khởi động toàn bộ stack không?
Có. docker compose run --rm --no-deps web sh khởi động một container đơn lẻ từ định nghĩa service web, bỏ qua các phụ thuộc của nó và xóa container khi bạn thoát. Hãy sử dụng exec thay thế khi container đã đang chạy, vì exec sẽ kết nối vào tiến trình đang chạy và cho bạn thấy trạng thái thực tế của service đó.