Tiêu đề có vẻ hơi loằng ngoằng. Bài toán của mình là dùng .env để đặt các biến môi trường và chỉ đưa vào các giá trị thật trên production. Dùng môi trường testing để test và dùng .gitignore để không push file .env lên github. Để đọc .env với Golang, mình dùng thư viện godotenv. Tuy nhiên, với Docker thì cách lấy biến lại hơi khác.
Cụ thể: mình sẽ vẫn dùng .env như thường, nhưng giờ không lấy biến môi trường thông qua godotenv như cũ. Quy trình mới sẽ dùng .evn –> docker environment (qua docker-compose.yml
) –> Golang code.

Nếu chọn cách .env –> docker –> code ta có 3 cách:
Cách 1: Tiếp tục dùng godotenv và phải copy file env từ code vào trong docker. Trong Dockerfile, bạn phải thêm lệnh sau COPY .env /app/.env
Cách này phải dùng thêm thư viện godotenv
Cách 2: Load nội dung của file .env
services: myservice: image: myapp env_file: - .env
Cách này tiện nếu có nhiều biến, không cần phải dùng godotenv để load file .env nữa, dùng luôn docker.
Cách 3: Load data của .env thông qua biến môi trường: hơi mắc công thiết lập nhưng không phải load file. Với cách này thì trong Go chỉ cần dùng os.Getnen(“DISCORD_BOT_TOKEN”) là lấy được biến đã thiết lập trong file .env
services: myservice: image: myapp environment: - MONGO_INITDB_DATABASE=${DATABASE} - MONGODB_USER=${USERNAME} - MONGODB_PASS=${PASSWORD} - DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN}
Chú ý:
env_file không hỗ trợ thay thế biến bên trong tệp .env (như ${VAR} bên trong .env sẽ không được mở rộng).
Các giá trị từ môi trường sẽ ghi đè lên các giá trị từ env_file.
Cá nhân mình với dự án Golang không dùng Docker sẽ dùng cách 1, còn với con discordbot đang viết thì dùng cách 3.
Cách 4: Vừa load file .env khi chạy dev, dùng docker cho production. Biến production sẽ lấy từ docker-composer.yml.

Thiết lập biến, load file .env khi chạy docker (Cách này không load file nhưng load biến môi trường trong file).

Update:
Nếu chạy code trên host thì việc kết nối với Postgres container sẽ thông qua localhost:5432, nhưng nếu chạy code trên container và kết nối với Postgrest container thì sẽ khác biệt, không thể dùng localhost. Trên Windows/Mac có thể dùng host.docker.internal
, nhưng Linux thì không.
Tóm tắt như sau:

Trên Linux thì mình sẽ dùng container_name:port để kết nối với Postgresql, bắt buộc phải thiết lập container của Golang + Postgresql và pgadmin cùng một network.
Nguyên nhân: Các container Docker chỉ có thể ping nhau theo IP chứ không phải theo tên container nếu để mặc định network là bridge. Do đó, nên tạo một customize network.