Khóa học
Thiết lập môi trường phát triển PostgreSQL không nên tốn hàng giờ cấu hình và xử lý sự cố — và với Docker, điều đó không còn nữa.
Docker cung cấp một cách đơn giản để khởi chạy PostgreSQL chỉ trong vài phút, bất kể hệ điều hành của bạn. Chỉ với vài lệnh, bạn có thể tạo một môi trường cơ sở dữ liệu đầy đủ chức năng, tách biệt với hệ thống, tránh xung đột phụ thuộc và rắc rối khi cài đặt.
Chạy PostgreSQL trong Docker cho phép bạn thoải mái thử nghiệm mà không lo làm hỏng thiết lập cục bộ. Bạn có thể dễ dàng tạo, sửa, hoặc xóa các phiên bản cơ sở dữ liệu, thử nhiều phiên bản PostgreSQL khác nhau, và đặt lại về trạng thái sạch bất cứ lúc nào.
Trong hướng dẫn này, tôi sẽ dẫn bạn qua mọi thứ cần biết để chạy PostgreSQL trong các container Docker cho trải nghiệm phát triển mượt mà.
>Chưa có nhiều kinh nghiệm với PostgreSQL? Khóa học nhập môn cho người mới bắt đầu của chúng tôi sẽ giúp bạn nắm bắt.
Vì sao nên dùng PostgreSQL trong Docker?
Trước khi có Docker, việc thiết lập cơ sở dữ liệu thường đồng nghĩa với việc theo các hướng dẫn cài đặt dài dòng, xử lý sự cố đặc thù hệ thống, và quản lý cẩn thận các phụ thuộc. Docker thay đổi hoàn toàn cách tiếp cận này.
>Rốt cuộc thì cơ sở dữ liệu PostgreSQL là gì? Tìm hiểu cách hoạt động, các trường hợp sử dụng phổ biến và tài nguyên.
Lợi ích của việc chạy PostgreSQL trong Docker
Docker mang đến một cách tinh gọn để chạy cơ sở dữ liệu PostgreSQL. So với cách cài đặt truyền thống, nó có vài lợi thế hiển nhiên:
- Cài đặt và thiết lập đơn giản: Với Docker, bạn có thể khởi tạo một phiên bản PostgreSQL chỉ với một lệnh. Không còn phải làm việc với trình quản lý gói, phụ thuộc hệ thống, hay các script cài đặt phức tạp. Cơ sở dữ liệu đi kèm cấu hình mặc định hợp lý và sẵn sàng dùng ngay.
- Môi trường đồng nhất giữa các thành viên: Mọi người trong nhóm của bạn đều có thiết lập PostgreSQL giống hệt nhau, bất kể hệ điều hành. Điều này loại bỏ vấn đề “chạy được trên máy tôi” vốn phổ biến trong các đội phát triển.
- Tách biệt với các thành phần hệ thống khác: Container Docker chạy tách biệt, nghĩa là phiên bản PostgreSQL của bạn sẽ không can thiệp vào phần mềm khác trên máy. Bạn có thể chạy đồng thời nhiều phiên bản PostgreSQL mà không xung đột, và việc gỡ bỏ PostgreSQL chỉ đơn giản là dừng và xóa container.
- Kiểm soát phiên bản cho môi trường cơ sở dữ liệu: Docker cho phép bạn chỉ định chính xác phiên bản PostgreSQL trong các tệp cấu hình. Nhờ đó, bạn có thể đảm bảo môi trường phát triển khớp hoàn toàn với môi trường sản xuất, và có thể thử nâng cấp một cách tách biệt trước khi áp dụng lên hệ thống sản xuất.
- Hiệu quả tài nguyên: Container Docker nhẹ hơn so với máy ảo. Chúng tiêu tốn ít tài nguyên hệ thống hơn nhưng vẫn cung cấp lợi ích tách biệt tương tự. Điều này có nghĩa bạn có thể chạy PostgreSQL cùng với các container khác mà không ảnh hưởng đáng kể đến hiệu năng hệ thống.
Khi nào nên dùng PostgreSQL trong Docker
Sau nhiều năm làm việc với cơ sở dữ liệu trong môi trường container hóa, tôi có thể khẳng định nó mang lại vô số lợi ích so với cách cài đặt truyền thống.
Vì tính tiện dụng, tôi chỉ nêu một vài trường hợp:
- Môi trường phát triển cục bộ: Với các nhà phát triển làm ứng dụng dùng PostgreSQL, Docker cho phép bắt đầu nhanh mà không cần thay đổi hệ thống cục bộ. Bạn có thể khớp chính xác phiên bản và cấu hình cơ sở dữ liệu dùng ở sản xuất, đảm bảo mã chạy ổn cục bộ sẽ chạy ổn khi triển khai.
- Kiến trúc microservices: Nếu bạn xây dựng ứng dụng theo microservices, Docker cho phép mỗi service có phiên bản cơ sở dữ liệu riêng khi cần. Điều này tăng mức độ tách biệt giữa các service và cho phép mỗi nhóm tự quản phụ thuộc cơ sở dữ liệu của mình.
- Pipeline CI/CD và kiểm thử tự động: Docker giúp dễ dàng tạo mới các phiên bản cơ sở dữ liệu để chạy kiểm thử. Mỗi lần chạy có thể bắt đầu với trạng thái sạch, nâng cao độ tin cậy của kiểm thử.
- Phát triển script migration cơ sở dữ liệu: Docker cung cấp môi trường an toàn để thử nghiệm migration. Bạn có thể xác minh script migration trên một cơ sở dữ liệu dùng một lần, khớp môi trường sản xuất, trước khi áp dụng lên hệ thống thật.
- Triển khai với Kubernetes: Nếu bạn dùng Kubernetes để điều phối, chạy PostgreSQL trong Docker là lựa chọn tự nhiên. Môi trường phát triển cục bộ có thể gần như trùng khớp với thiết lập Kubernetes sản xuất, giúp quy trình từ phát triển đến sản xuất liền mạch.
Tóm lại, PostgreSQL dạng container rất hữu ích cho phát triển và kiểm thử, nhưng cần lưu ý rằng quản lý triển khai cơ sở dữ liệu cho môi trường sản xuất đòi hỏi cân nhắc thêm về lưu trữ bền vững, sao lưu và tính sẵn sàng cao.
Tôi sẽ đề cập đến một số điểm này ở các phần sau của bài viết.
Thiết lập PostgreSQL trong Docker
Thứ duy nhất bạn cần để chạy cơ sở dữ liệu Postgres trong Docker là chính Docker engine.
Trong phần này, tôi sẽ hướng dẫn bạn quy trình bao gồm các điều kiện tiên quyết và chạy một cơ sở dữ liệu PostgreSQL đầy đủ chức năng trong container Docker.
Điều kiện tiên quyết
Trước khi bắt đầu với PostgreSQL trong Docker, bạn cần cài đặt Docker trên hệ thống.
Cách cài đặt khác nhau tùy hệ điều hành. Người dùng Windows và macOS có thể đơn giản cài Docker Desktop, một giao diện đồ họa dễ dùng để quản lý container. Tải về từ trang Docker chính thức.
Người dùng Linux có thể cài trực tiếp Docker Engine bằng trình quản lý gói của bản phân phối. Ví dụ, trên Ubuntu:
sudo apt update
sudo apt install docker.io
sudo systemctl enable --now docker
Ngoài việc đã cài Docker, bạn nên quen với các lệnh terminal cơ bản và các khái niệm Docker cơ bản như image, container và volume. Những hướng dẫn thực hành này từ DataCamp sẽ hỗ trợ bạn:
- Docker cho người mới: Hướng dẫn thực hành về container
- Cài Docker trên Ubuntu: Từ thiết lập đến container đầu tiên
Kéo image Docker của PostgreSQL
Trước khi chạy PostgreSQL, bạn cần tải image Docker chính thức của PostgreSQL từ Docker Hub. Image này đóng vai trò mẫu để tạo container.
Để kéo phiên bản PostgreSQL mới nhất, mở terminal hoặc command prompt và chạy:
docker pull postgres
Lệnh này tải phiên bản ổn định mới nhất của PostgreSQL. Nếu bạn cần phiên bản cụ thể, có thể chỉ định bằng tag:
docker pull postgres:17

Hình 1 - Kéo phiên bản ổn định mới nhất của image cơ sở dữ liệu PostgreSQL
Một số tag image PostgreSQL thường dùng gồm:
postgres:latest- Phiên bản PostgreSQL ổn định mới nhấtpostgres:17- PostgreSQL phiên bản 14.x (bản vá mới nhất của phiên bản 17)postgres:17.4- Một phiên bản cụ thể (trong trường hợp này là 17.4).postgres:bookworm- PostgreSQL xây dựng trên bản phân phối Debian Bookworm.
Bạn có thể xem tất cả tag có sẵn trên trang PostgreSQL Docker Hub chính thức.
Chạy PostgreSQL trong container Docker
Khi đã có image PostgreSQL, bạn có thể tạo và khởi động một container chỉ với một lệnh:
docker run --name postgres-db -e POSTGRES_PASSWORD=mypassword postgres

Hình 2 - Khởi động một container PostgreSQL
Lệnh này tạo một container mới tên là postgres-db và đặt biến môi trường cho mật khẩu PostgreSQL.
Tuy nhiên, lệnh cơ bản này còn hạn chế. Tôi khuyến nghị dùng thêm các tùy chọn sau:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mypassword \
-e POSTGRES_USER=myuser \
-e POSTGRES_DB=mydatabase \
-p 5432:5432 \
-v postgres-data:/var/lib/postgresql/data \
-d postgres

Hình 3 - Khởi động container PostgreSQL với biến môi trường ở chế độ nền
Tôi sẽ phân tích các tùy chọn bổ sung này:
- Biến môi trường:
POSTGRES_PASSWORD: Đặt mật khẩu cho superuser PostgreSQL (bắt buộc).POSTGRES_USER: Tạo superuser mới với tên này (mặc định là "postgres" nếu không chỉ định).POSTGRES_DB:Tạo cơ sở dữ liệu mới với tên này (mặc định là tên người dùng nếu không chỉ định).
- Ánh xạ cổng (
-p 5432:5432) ánh xạ cổng PostgreSQL của container (5432) sang cùng cổng trên máy chủ của bạn, cho phép kết nối qua localhost:5432. - Gắn volume (
-v postgres-data:/var/lib/postgresql/data) tạo một volume Docker tên postgres-data để lưu trữ file dữ liệu cơ sở dữ liệu bên ngoài container. Điều này đảm bảo dữ liệu không bị mất khi container dừng hoặc bị xóa. - Cờ
-dđảm bảo container chạy ở chế độ nền. Nói cách khác, container chạy ở background.
Bạn có thể xác nhận container đang chạy bằng:
docker ps

Hình 4 - Liệt kê tất cả container đang chạy
Ở phần tiếp theo, tôi sẽ hướng dẫn bạn cấu hình thêm container PostgreSQL cho các trường hợp sử dụng cụ thể.
Cấu hình PostgreSQL trong Docker
Thiết lập cơ bản ở phần trước đủ để bạn bắt đầu, nhưng cho nhu cầu nâng cao, bạn sẽ muốn tùy chỉnh container PostgreSQL.
Đó chính là nội dung phần này.
Thiết lập lưu trữ bền vững với volumes
Một trong những khía cạnh quan trọng nhất khi chạy cơ sở dữ liệu trong Docker là đảm bảo dữ liệu tồn tại vượt qua vòng đời của container. Mặc định, mọi dữ liệu trong container sẽ mất khi container bị xóa. Với cơ sở dữ liệu, điều này hầu như không bao giờ là mong muốn.
Docker volume cung cấp giải pháp bằng cách lưu dữ liệu bên ngoài hệ thống file của container.
Để thiết lập, bắt đầu bằng việc tạo một volume có tên:
docker volume create postgres-data
Bạn có thể tuỳ chọn kiểm tra chi tiết volume bằng lệnh sau:
docker volume inspect postgres-data

Hình 5 - Liệt kê chi tiết volume
Giờ đây, khi khởi động container PostgreSQL, hãy gắn volume vào thư mục dữ liệu của PostgreSQL:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-v postgres-data:/var/lib/postgresql/data \
-d postgres
Tham số -v postgres-data:/var/lib/postgresql/data kết nối volume đã đặt tên với thư mục dữ liệu của container.
Tóm lại, dùng volumes cho PostgreSQL có các lợi thế sau:
- Dữ liệu vẫn tồn tại ngay cả khi bạn xóa container.
- Bạn có thể dừng, khởi động lại, hoặc nâng cấp container mà không mất dữ liệu.
- Bạn có thể sao lưu dữ liệu bằng cách sao lưu volume.
- Hiệu năng tốt hơn so với bind mount (đặc biệt trên macOS và Windows).
Mở cổng để kết nối tới PostgreSQL
Để kết nối tới cơ sở dữ liệu PostgreSQL từ các ứng dụng chạy trên máy chủ của bạn, bạn cần mở cổng PostgreSQL (5432) cho hệ thống cục bộ.
Cách đơn giản nhất là ánh xạ cổng 5432 của container sang cùng cổng trên máy chủ:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 5432:5432 \
-d postgres
Tham số -p 5432:5432 ánh xạ cổng 5432 của container sang cổng 5432 trên máy của bạn.
Nếu trên máy đã có PostgreSQL hoặc dịch vụ khác dùng cổng 5432, bạn có thể ánh xạ sang cổng khác:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 5433:5432 \
-d postgres
Giờ đây, cổng 5432 của container được ánh xạ sang cổng 5433 trên máy của bạn. Khi kết nối, bạn cần chỉ định cổng 5433 thay vì mặc định 5432.
Mặc định, cổng được mở trên mọi interface mạng (0.0.0.0). Bạn có thể giới hạn về localhost để tăng bảo mật:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 127.0.0.1:5432:5432 \
-d postgres
Thiết lập này chỉ cho phép kết nối từ máy cục bộ, không cho các máy khác trong mạng.
Cấu hình các thiết lập PostgreSQL
Bạn có thể thay đổi nhiều thiết lập mặc định của PostgreSQL khi khởi tạo container. Cách phổ biến, dù không phải duy nhất, là dùng biến môi trường.
Dưới đây là một vài biến bạn có thể dùng để cấu hình cơ sở dữ liệu:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-e POSTGRES_USER=myuser \
-e POSTGRES_DB=mydatabase \
-e POSTGRES_INITDB_ARGS="--data-checksums" \
-e POSTGRES_HOST_AUTH_METHOD=scram-sha-256 \
-d postgres
Và đây là ý nghĩa của từng biến:
POSTGRES_PASSWORD: Đặt mật khẩu cho superuser (bắt buộc).POSTGRES_USER: Đặt tên superuser (mặc định là "postgres").POSTGRES_DB: Đặt tên cơ sở dữ liệu mặc định (mặc định là tên người dùng).POSTGRES_INITDB_ARGS: Truyền tham số cho lệnhinitdbcủa PostgreSQL.POSTGRES_HOST_AUTH_METHOD: Đặt phương thức xác thực.
Bên cạnh biến môi trường, bạn cũng có thể tùy chỉnh cấu hình PostgreSQL để thực hiện các thay đổi nâng cao cho cấu hình cơ sở dữ liệu.
Một số thiết lập PostgreSQL thường được tùy chỉnh:
max_connections: Kiểm soát số lượng kết nối PostgreSQL chấp nhận (mặc định là 100).shared_buffers: Đặt bộ nhớ dùng cho cache (mặc định thường quá thấp cho sản xuất).work_mem: Bộ nhớ dùng cho các thao tác truy vấn.maintenance_work_mem: Bộ nhớ dùng cho các tác vụ bảo trì.
Trong một triển khai thực tế, hãy bắt đầu bằng cách tạo một tệp, gọi là my-postgres-conf:
max_connections = 200
shared_buffers = 1GB
work_mem = 16MB
maintenance_work_mem = 256MB
Giờ hãy gắn tệp này khi chạy container:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-v ./my-postgres.conf:/etc/postgresql/postgresql.conf \
-v postgres-data:/var/lib/postgresql/data \
-d postgres \
-c 'config_file=/etc/postgresql/postgresql.conf'
Tóm lại, bằng cách cấu hình lưu trữ bền vững, truy cập mạng, và các thiết lập PostgreSQL đúng cách, bạn có thể tạo một môi trường PostgreSQL dựa trên Docker hoạt động chính xác theo ý muốn. Image cơ sở postgres:latest đúng nghĩa là nền tảng — còn rất nhiều thứ bạn có thể tinh chỉnh.
Ở phần tiếp theo, tôi sẽ hướng dẫn cách kết nối tới cơ sở dữ liệu PostgreSQL đang chạy trong Docker.
Kết nối tới PostgreSQL chạy trong Docker
Giờ khi container PostgreSQL đã chạy, bước tiếp theo là kết nối vào. Rốt cuộc, bạn chạy cơ sở dữ liệu để làm gì nếu không phải để sử dụng?
Trong phần này, tôi sẽ chỉ cho bạn hai cách để kết nối tới cơ sở dữ liệu PostgreSQL dạng container: dùng công cụ dòng lệnh psql và dùng giao diện đồ họa.
Để tham khảo, tôi đang chạy container cơ sở dữ liệu với lệnh sau:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-e POSTGRES_USER=myuser \
-e POSTGRES_DB=mydatabase \
-v postgres-data:/var/lib/postgresql/data \
-p 5432:5432 \
-d postgres
Kết nối bằng công cụ dòng lệnh psql
psql là công cụ dòng lệnh chính thức của PostgreSQL cho phép bạn tương tác với cơ sở dữ liệu bằng các lệnh SQL.
Để kết nối tới cơ sở dữ liệu PostgreSQL chạy trong container từ máy chủ của bạn, chạy lệnh sau và nhớ cập nhật giá trị user và database:
docker exec -it postgres-db psql -U myuser -d mydatabase

Hình 6 - Kết nối tới cơ sở dữ liệu Postgres bằng psql
Vậy là xong!
Nếu bạn chưa rõ lệnh trên làm gì, đây là phần giải thích đơn giản:
docker exec -it postgres-db: Chạy một lệnh tương tác bên trong container tên "postgres-db".psql -U myuser -d mydatabase: Khởi động psql, kết nối với tư cách "myuser" tới cơ sở dữ liệu "mydatabase".
Nếu gặp khó khăn khi kết nối, hãy kiểm tra các vấn đề thường gặp sau:
- Xác nhận container đang chạy với
docker ps. - Kiểm tra ánh xạ cổng với
docker port postgres-db.
Kết nối bằng công cụ giao diện đồ họa (GUI)
Nhiều nhà phát triển thích dùng công cụ đồ họa hơn CLI — bản thân tôi cũng vậy. pgAdmin là lựa chọn phổ biến và miễn phí cho PostgreSQL, nhưng quy trình kết nối tương tự cho các công cụ khác như DBeaver, DataGrip, hoặc TablePlus.
Việc cài đặt pgAdmin khá đơn giản, nên tôi sẽ không đề cập ở đây.
Giả sử bạn đã cài và mở pgAdmin, nhấp phải vào "Servers" trong bảng trình duyệt và chọn "Register > Server". Ở tab General, đặt tên cho kết nối của bạn:

Hình 7 - Thẻ General trong pgAdmin
Sau đó chuyển sang thẻ "Connection" và nhập các thông tin sau:
- Host name/address:
localhost - Port:
5432(hoặc cổng bạn đã ánh xạ) - Maintenance database:
mydatabase - Username:
myuser - Password: Mật khẩu PostgreSQL của bạn

Hình 8 - Thẻ Connection trong pgAdmin
Cuối cùng, nhấp "Save" để kết nối:

Hình 9 - Kết nối thành công
Khi đã kết nối, bạn có thể bắt đầu làm việc với cơ sở dữ liệu như với một phiên bản PostgreSQL cài cục bộ hoặc cung cấp trên đám mây. Điều tuyệt vời của Docker là từ góc nhìn của ứng dụng hoặc công cụ khách, không có gì khác biệt — đó chỉ là một cơ sở dữ liệu PostgreSQL truy cập tại địa chỉ đã chỉ định.
>Cần truy cập cơ sở dữ liệu PostgreSQL bằng lập trình? Tìm hiểu cách truy cập từ Python.
Ở phần tiếp theo, tôi sẽ trình bày cách quản lý container PostgreSQL, bao gồm dừng, khởi động và giám sát.
Quản lý PostgreSQL trong Docker
Chạy một cơ sở dữ liệu PostgreSQL trong container và kết nối vào là một chuyện, quản lý lại là chuyện khác. May mắn là bạn có một loạt lệnh sẵn sàng sử dụng.
Trong phần này, tôi sẽ đề cập các thao tác thiết yếu như dừng và khởi động container, xem log, và giữ phiên bản PostgreSQL luôn cập nhật.
Dừng, khởi động lại và xóa container PostgreSQL
Công cụ dòng lệnh của Docker cho phép bạn quản lý vòng đời container PostgreSQL.
Để dừng một container PostgreSQL đang chạy, dùng:
docker stop postgres-db
Tương tự, chạy lệnh sau khi bạn cần khởi động lại:
docker start postgres-db

Hình 10 - Dừng và khởi động container
Nếu bạn muốn khởi động lại một container đang chạy, hữu ích sau khi thay đổi một số cấu hình, chạy lệnh sau:
docker restart postgres-db
Trong trường hợp bạn đã hoàn toàn xong với container và muốn xóa nó, dùng hai lệnh sau:
docker stop postgres-db
docker rm postgres-db
Hãy nhớ rằng xóa container không xóa dữ liệu của bạn nếu bạn đã thiết lập volume đúng cách. Dữ liệu vẫn nằm trong volume postgres-data đã tạo trước đó.
Bạn có thể xác nhận container đã bị xóa bằng cách chạy:
docker ps -a
Cờ -a hiển thị tất cả container, bao gồm cả container đã dừng. Nếu container của bạn đã bị xóa thành công, nó sẽ không còn trong danh sách:

Hình 11 - Liệt kê tất cả container
Kiểm tra log
Khi có sự cố hoặc bạn muốn theo dõi hoạt động của cơ sở dữ liệu, kiểm tra log là bước đầu tốt.
Chạy lệnh này để xem log của container PostgreSQL:
docker logs postgres-db
Lệnh này hiển thị toàn bộ log kể từ khi container khởi động. Với lượng log lớn, bạn có thể giới hạn đầu ra, ví dụ chỉ lấy 50 dòng cuối:
docker logs --tail 50 postgres-db

Hình 12 - Xem log container
Mặt khác, nếu bạn muốn theo dõi log theo thời gian thực, hãy chạy lệnh sau:
docker logs -f postgres-db

Hình 13 - Xem log container theo thời gian thực
Cách này đặc biệt hữu ích khi gỡ lỗi vấn đề kết nối hoặc theo dõi hoạt động cơ sở dữ liệu trong quá trình phát triển.
Nhấn Ctrl+C/CMD+C để dừng theo dõi log.
Cập nhật PostgreSQL trong Docker
Theo thời gian, bạn sẽ muốn cập nhật phiên bản PostgreSQL để nhận tính năng mới, cải thiện hiệu năng và bản vá bảo mật.
Tại thời điểm viết bài, postgres:17.4 là phiên bản mới nhất, nhưng giả sử postgres:17.5 vừa phát hành. Phần này sẽ chỉ bạn cách cập nhật phiên bản cơ sở dữ liệu trong container.
Trước tiên, kéo image PostgreSQL mới nhất (hoặc phiên bản cụ thể):
docker pull postgres:17.5
Tiếp theo, dừng và xóa container hiện tại:
docker stop postgres-db
docker rm postgres-db
Cuối cùng, tạo container mới với cùng volume:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-e POSTGRES_USER=myuser \
-e POSTGRES_DB=mydatabase \
-v postgres-data:/var/lib/postgresql/data \
-p 5432:5432 \
-d postgres:17.5
Vì bạn dùng cùng volume (postgres-data), toàn bộ dữ liệu hiện có sẽ được giữ nguyên.
Nếu bạn nâng cấp lên phiên bản lớn mới (ví dụ 17 lên 18), PostgreSQL sẽ tự động chạy các migration dữ liệu cần thiết khi khởi động. Chỉ cần lưu ý:
- Nâng cấp phiên bản lớn nên được thử nghiệm trước ở môi trường không phải sản xuất.
- Luôn sao lưu volume dữ liệu trước khi nâng cấp phiên bản lớn.
- Xem ghi chú phát hành của PostgreSQL để biết thay đổi phá vỡ tương thích.
Để tạo bản sao lưu trước khi nâng cấp, chạy lệnh sau:
docker run --rm -v postgres-data:/data -v $(pwd):/backup postgres:17.4 \
bash -c "pg_dumpall -U myuser > /backup/postgres_backup.sql"
Lệnh này tạo một tệp sao lưu SQL trong thư mục hiện tại của bạn, có thể dùng để khôi phục dữ liệu nếu có sự cố.
>Bạn có thể thấy Cheat Sheet PostgreSQL cơ bản cũng khá hữu ích như tài liệu tham khảo nhanh khi làm việc trong Docker.
Ở phần tiếp theo, tôi sẽ đề cập các phương pháp hay nhất khi dùng PostgreSQL trong Docker, bao gồm cân nhắc bảo mật và mẹo tối ưu hóa.
Thực hành tốt nhất khi dùng PostgreSQL trong Docker
Tính linh hoạt của Docker đi kèm trách nhiệm. Phần này, tôi sẽ chia sẻ một số thực hành tốt nhất để đảm bảo thiết lập PostgreSQL dạng container của bạn đáng tin cậy, an toàn và theo chuẩn ngành.
Giữ an toàn dữ liệu với sao lưu định kỳ
Bất kể bạn chạy PostgreSQL thế nào, sao lưu định kỳ là bắt buộc. Tôi đã nhắc đến sao lưu ở phần trước, nhưng ở đây sẽ chi tiết hơn.
Cách đơn giản nhất để sao lưu cơ sở dữ liệu PostgreSQL chạy trong Docker là dùng pg_dump:
docker exec -t postgres-db pg_dump -U myuser mydatabase > backup.sql

Hình 14 - Sao lưu PostgreSQL
Để sao lưu toàn bộ tất cả cơ sở dữ liệu, bao gồm role và tablespace, hãy dùng pg_dumpall:
docker exec -t postgres-db pg_dumpall -U myuser > full_backup.sql

Hình 15 - Sao lưu toàn bộ cơ sở dữ liệu PostgreSQL
Hình này chỉ hiển thị một vài lệnh sao lưu, vì không thể nhét toàn bộ vào một màn hình.
Để tự động hóa việc sao lưu, bạn có thể tạo script shell đơn giản và chạy bằng cron:
#!/bin/bash
# backup.sh
TIMESTAMP=$(date +"%Y%m%d")
BACKUP_DIR="/Users/dradecic/Documents/pg-backups"
# Make sure the backup directory exists
mkdir -p $BACKUP_DIR
# Create the backup
docker exec postgres-db pg_dumpall -U myuser | gzip > $BACKUP_DIR/postgres_$TIMESTAMP.sql.gz
# Remove backups older than 30 days
find $BACKUP_DIR -name "postgres_*.sql.gz" -mtime +30 -delete
Cấp quyền thực thi cho script và chạy nó:
chmod +x backup.sh
bash backup.sh

Hình 16 - Chạy script sao lưu cơ sở dữ liệu PostgreSQL
Để tự động hóa hoàn toàn việc sao lưu, bạn có thể thêm script vào crontab để chạy hàng ngày:
0 3 * * * /path/to/backup.sh
Lịch này chạy sao lưu mỗi ngày lúc 3 giờ sáng, nhưng tất nhiên bạn có thể điều chỉnh thời gian và tần suất theo nhu cầu.
>Xem hướng dẫn đầy đủ về cron job của tôi để tìm hiểu thêm về công cụ tự động hóa hữu ích này.
Đối với môi trường sản xuất, hãy cân nhắc lưu trữ bản sao lưu ở ngoài site hoặc trên đám mây để phục hồi sau thảm họa.
Dùng volume có tên cho lưu trữ bền vững
Tuy tôi đã đề cập về volume ở trên, nhưng cũng đáng để xem lại sâu hơn.
Theo nguyên tắc, bạn không bao giờ nên chạy PostgreSQL trong Docker mà không cấu hình volume đúng cách. Nếu không, dữ liệu sẽ bị mất khi container bị xóa hoặc khi Docker dọn dẹp.
Dùng volume có tên (thay vì volume ẩn danh) giúp việc sao lưu và quản lý dữ liệu dễ dàng hơn nhiều:
# Create a named volume
docker volume create postgres-data
# Use it when running the container
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-v postgres-data:/var/lib/postgresql/data \
-d postgres
Không có gì mới ở đây.
Volume có tên cũng dễ sao lưu hơn. Để tạo bản sao lưu toàn bộ volume, chạy lệnh:
docker run --rm -v postgres-data:/data -v $(pwd):/backup alpine tar czf /backup/postgres-data-backup.tar.gz /data
Lệnh này sẽ tạo tệp postgres-data-backup.tar.gz trong cùng thư mục nơi bạn chạy lệnh.
Giờ để khôi phục volume này, chạy lệnh sau:
docker run --rm -v postgres-data:/data -v $(pwd):/backup alpine sh -c "cd /data && tar xzf /backup/postgres-data-backup.tar.gz --strip 1"
Vậy là xong!
Bảo mật PostgreSQL trong Docker
Đối với cơ sở dữ liệu, bảo mật không bao giờ nên là suy nghĩ sau cùng. Phần phụ này sẽ hướng dẫn bạn một số thực hành thiết yếu để bảo mật container PostgreSQL.
Dùng mật khẩu mạnh và duy nhất
Tránh dùng mật khẩu mặc định hoặc yếu. Hãy tạo một mật khẩu mạnh, ngẫu nhiên cho superuser PostgreSQL:
export POSTGRES_PASSWORD=$(openssl rand -base64 32)
echo "$POSTGRES_PASSWORD" > postgres-password.txt
docker run --name postgres-db \
-e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
-v postgres-data:/var/lib/postgresql/data \
-d postgres

Hình 17 - Dùng mật khẩu an toàn
Lưu mật khẩu này một cách an toàn, như trong trình quản lý mật khẩu hoặc tệp biến môi trường không đưa vào hệ thống quản lý mã nguồn.
Giới hạn truy cập mạng
Mặc định, Docker mở cổng PostgreSQL trên tất cả interface. Để tăng bảo mật, đặc biệt trong sản xuất, hãy giới hạn truy cập về localhost:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 127.0.0.1:5432:5432 \
-v postgres-data:/var/lib/postgresql/data \
-d postgres
Dùng cấu hình PostgreSQL tùy chỉnh
Tạo cấu hình PostgreSQL an toàn hơn bằng cách điều chỉnh các tham số như dưới đây:
# Require SSL
ssl = on
ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'
# Limit connection attempts
max_connections = 100
authentication_timeout = 1min
# Restrict access
listen_addresses = 'localhost'
Gắn tệp cấu hình này khi khởi động container:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-v ./pg_hba.conf:/var/lib/postgresql/data/pg_hba.conf \
-v ./postgresql.conf:/var/lib/postgresql/data/postgresql.conf \
-v postgres-data:/var/lib/postgresql/data \
-d postgres
Thường xuyên cập nhật image PostgreSQL
Giữ phiên bản PostgreSQL của bạn được cập nhật để nhận bản vá bảo mật mới nhất:
docker pull postgres:latest
docker stop postgres-db
docker rm postgres-db
# Then recreate with the latest image
Những thực hành tốt nhất này sẽ giúp bạn tạo môi trường PostgreSQL trong Docker đáng tin cậy và an toàn hơn, phù hợp cho cả phát triển và sản xuất.
Ở phần tiếp theo, tôi sẽ hướng dẫn cách khắc phục các vấn đề thường gặp khi chạy PostgreSQL trong Docker.
Khắc phục sự cố PostgreSQL trong Docker
Sớm hay muộn, bạn sẽ gặp sự cố khi chạy PostgreSQL trong Docker. Tôi sẽ đề cập các vấn đề thường gặp và cách giải quyết trong phần này, giúp bạn tiết kiệm thời gian và giảm bực bội.
Các vấn đề thường gặp với container PostgreSQL
Một vấn đề phổ biến là container thoát ngay sau khi khởi động. Nếu đúng vậy, hãy kiểm tra log để xác định nguyên nhân:
docker logs postgres-db
Lỗi có thể liên quan đến quyền truy cập với volume được gắn. Nếu vậy, bạn sẽ thấy thông báo log tương tự:
initdb: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted
Để giải quyết, kiểm tra quyền sở hữu và phân quyền của volume rồi sửa nếu cần:
# Check the ownership
docker run --rm -v postgres-data:/data alpine ls -la /data
# Fix the permissions
docker run --rm -v postgres-data:/data alpine chmod 700 /data
Một vấn đề khác là thiếu biến môi trường bắt buộc. Thông báo log điển hình khi xảy ra sẽ như sau:
Database is uninitialized and superuser password is not specified
Để khắc phục, hãy đảm bảo bạn đang đặt biến môi trường POSTGRES_PASSWORD bắt buộc — hoặc bất kỳ biến môi trường cần thiết nào khác:
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-v postgres-data:/var/lib/postgresql/data \
-d postgres
Lỗi “Thư mục dữ liệu không trống nhưng thiếu file PostgreSQL” cũng khá phổ biến. Bạn có thể thấy thông báo log sau:
PostgreSQL Database directory appears to contain a database; Skipping initialization
Sau đó là các lỗi về thiếu file.
Điều này thường xảy ra khi bạn gắn một volume chứa file nhưng không phải cơ sở dữ liệu PostgreSQL hợp lệ. Bạn có thể cần khởi tạo lại bằng một volume mới:
docker volume create postgres-data-new
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mysecretpassword \
-v postgres-data-new:/var/lib/postgresql/data \
-d postgres
Giải quyết vấn đề kết nối
Nếu bạn không thể kết nối tới cơ sở dữ liệu PostgreSQL chạy trong container, hãy bắt đầu bằng cách xác nhận container đang chạy:
docker ps | grep postgres-db
Nếu không thấy, có thể container đã bị crash. Hãy kiểm tra log như đã mô tả trước đó.
Nếu có trong danh sách nhưng vẫn không kết nối được, hãy xác minh ánh xạ cổng:
docker port postgres-db
Bạn sẽ thấy gì đó tương tự thế này:

Hình 18 - Ánh xạ cổng của container
Nếu không, có thể ánh xạ cổng chưa đúng. Hãy tạo lại container với tùy chọn -p phù hợp.
Nếu vẫn không thể kết nối tới cơ sở dữ liệu, đã đến lúc kiểm tra thiết lập kết nối. Kiểm tra các tham số sau:
- Hostname:
localhosthoặc127.0.0.1(không phải tên container). - Port: Cổng trên máy theo ánh xạ (thường là 5432).
- Username: Giá trị của
POSTGRES_USER(mặc định là "postgres"). - Password: Giá trị của
POSTGRES_PASSWORD. - Database: Giá trị của
POSTGRES_DB(mặc định trùngPOSTGRES_USER).
Hãy thử lại sau khi xử lý các điểm trên. Nếu vẫn gặp vấn đề, bạn nên kiểm tra kết nối từ bên trong container:
docker exec -it postgres-db psql -U postgres
Nếu lệnh này hoạt động, vấn đề nằm ở ánh xạ cổng hoặc mạng bên ngoài.
Cuối cùng, bạn có thể kiểm tra vấn đề tường lửa. Tường lửa hệ thống có thể chặn kết nối tới cổng PostgreSQL, hãy kiểm tra:
# Linux
sudo iptables -L | grep 5432
# macOS
sudo pfctl -sr | grep 5432
Bằng cách kiểm tra các vấn đề thường gặp này, bạn có thể xác định và giải quyết hầu hết trục trặc với PostgreSQL trong Docker. Nếu vẫn bế tắc, tài liệu và diễn đàn cộng đồng của PostgreSQL và Docker là nguồn lực tuyệt vời cho việc khắc phục sự cố cụ thể hơn.
Tổng kết cơ sở dữ liệu PostgreSQL trong Docker
Vậy là bạn đã có — hướng dẫn toàn diện để cấu hình và chạy cơ sở dữ liệu PostgreSQL trong Docker! Tôi đã trình bày mọi thứ bạn cần để bắt đầu, từ thiết lập container đầu tiên đến cấu hình, kết nối và quản lý cơ sở dữ liệu.
Các lựa chọn PostgreSQL truyền thống, như cài cục bộ hoặc cung cấp trên đám mây, thường không tối ưu hoặc tốn kém cho mục đích phát triển. Docker lấp đầy khoảng trống này. Dù bạn dùng cho phát triển cục bộ, kiểm thử hay thậm chí môi trường sản xuất, PostgreSQL dạng container mang lại sự linh hoạt và nhất quán khó có thể thay thế.
Giờ đây bạn đã sẵn sàng tích hợp cơ sở dữ liệu Postgres dạng container vào ứng dụng của mình.
Nếu muốn tìm hiểu sâu hơn, tôi khuyến nghị các khóa học sau từ DataCamp:
FAQs
Vì sao tôi nên chạy PostgreSQL trong Docker thay vì cài đặt truyền thống?
Sử dụng PostgreSQL trong Docker mang đến cài đặt đơn giản, môi trường nhất quán trên các máy khác nhau và tách biệt với các thành phần hệ thống khác. Bạn có thể chạy đồng thời nhiều phiên bản PostgreSQL mà không xung đột, dễ dàng nâng cấp hoặc hạ cấp, và cho phép thiết lập/thu hồi nhanh cho phát triển và kiểm thử. Container Docker cũng dùng ít tài nguyên hệ thống hơn so với máy ảo.
Làm sao tôi kết nối tới cơ sở dữ liệu PostgreSQL chạy trong Docker?
Bạn có thể kết nối tới cơ sở dữ liệu PostgreSQL chạy trong Docker bằng lệnh docker exec -it postgres-db psql -U myuser -d mydatabase để truy cập công cụ dòng lệnh psql trực tiếp trong container. Ngoài ra, bạn có thể dùng các công cụ GUI như pgAdmin, DBeaver hoặc TablePlus bằng cách kết nối tới localhost (hoặc 127.0.0.1) trên cổng bạn đã ánh xạ (thường là 5432) với tên người dùng và mật khẩu đã cấu hình.
Điều gì xảy ra với dữ liệu PostgreSQL của tôi khi xóa container Docker?
Khi bạn xóa một container Docker, mọi dữ liệu lưu bên trong container sẽ mất trừ khi bạn đã thiết lập volume. Bằng cách dùng volume có tên (như docker volume create postgres-data), dữ liệu cơ sở dữ liệu của bạn sẽ tồn tại bên ngoài hệ thống file của container. Điều này có nghĩa bạn có thể an toàn dừng, xóa hoặc nâng cấp container PostgreSQL mà không mất dữ liệu, miễn là bạn gắn cùng volume khi tạo container mới.
Làm sao tôi sao lưu cơ sở dữ liệu PostgreSQL chạy trong Docker?
Để sao lưu cơ sở dữ liệu PostgreSQL chạy trong Docker, bạn có thể dùng lệnh pg_dump với: docker exec -t postgres-db pg_dump -U myuser mydatabase > backup.sql. Để sao lưu toàn bộ bao gồm tất cả cơ sở dữ liệu và role, dùng pg_dumpall. Bạn có thể tự động hóa sao lưu bằng script shell với cron để chạy theo lịch, kèm nén và xoay vòng các bản sao lưu cũ.
