Environment config (.env / environment) ใน Docker Compose
บทนี้จะสอนการจัดการ environment variables ใน Docker Compose แบบละเอียดสำหรับผู้เริ่มต้น ตั้งแต่แนวคิดพื้นฐาน ความต่างระหว่าง .env, environment, env_file ไปจนถึงการแทนค่าตัวแปร ความปลอดภัยของ secret และแนวทางใช้งานจริงใน dev / test / production
ภาพ flow: .env -> compose interpolation (${...}) -> environment ใน service -> container runtime
ภาพเปรียบเทียบ: environment เหมาะกับค่าน้อยและต้องการความชัดเจน ส่วน env_file เหมาะกับคีย์จำนวนมาก
ภาพเตือนความปลอดภัย: หลีกเลี่ยงการ commit ไฟล์ secret และใช้ .env.example แทนค่าจริง
ภาพจำสำคัญบทนี้
.env ใช้แทนค่าใน compose, environment และ env_file ใช้ส่งค่าจริงเข้า container และ secret ต้องไม่หลุดเข้า git
ส่วนที่ 1
1) Environment variables คืออะไร
Environment variables คือตัวแปรคอนฟิกที่ส่งจากภายนอกเข้าแอปตอนรัน (runtime) โดยไม่ต้องแก้โค้ดโดยตรง ให้จำง่าย ๆ ว่าโค้ดคือพฤติกรรม ส่วน environment คือค่าตั้งต้นที่เปลี่ยนได้ตามสภาพแวดล้อม เช่นเครื่องนักพัฒนา, เซิร์ฟเวอร์ทดสอบ, หรือโปรดักชัน ตัวอย่างค่า env ที่เจอบ่อย: - `PORT` บอกพอร์ตที่แอปรับ request - `NODE_ENV` บอกโหมดการทำงาน - `DATABASE_URL` บอกจุดเชื่อมต่อฐานข้อมูล
ประเด็นที่ 1
เปลี่ยนคอนฟิกได้โดยไม่ต้องแก้โค้ด
ประเด็นที่ 2
แอปเดียวกันใช้ได้หลาย environment
ประเด็นที่ 3
แยกค่าที่ละเอียดอ่อนออกจาก source code
ส่วนที่ 2
2) ทำไมระบบหลาย service ต้องใช้ environment config
ในระบบ multi-service (เช่น `web`, `api`, `db`) แต่ละ service ต้องมีค่าคอนฟิกของตัวเอง และต้องคุยกันได้ถูกปลายทาง ถ้า hardcode ค่าไว้ในโค้ดทุกจุด จะเปลี่ยน environment ลำบากมาก และเสี่ยงพลาดตอน deploy
| Service | ตัวแปรที่มักใช้ | ตัวอย่าง |
|---|---|---|
| web | PORT, NODE_ENV | PORT=3000 |
| api | PORT, NODE_ENV, DATABASE_URL | DATABASE_URL=postgres://... |
| db | DB_USER, DB_PASSWORD | DB_USER=app, DB_PASSWORD=secret |
ส่วนที่ 3
3) .env file คืออะไร
`.env` คือไฟล์ข้อความที่เก็บคู่ `KEY=VALUE` สำหรับให้ Docker Compose ใช้แทนค่าตัวแปรในไฟล์ compose เช่น `${PORT}` หรือ `${NODE_ENV}` จุดสำคัญ: `.env` ใช้เพื่อ interpolation ใน compose file เป็นหลัก ไม่ใช่หมายความว่าจะถูกส่งเข้า container อัตโนมัติทุกตัว
- เหมาะกับค่าที่ต้องใช้ซ้ำหลายจุดใน compose
- ช่วยลด hardcode ค่าในไฟล์ YAML
- ควรมีไฟล์ `.env.example` ไว้บอกทีมว่าต้องตั้งค่าอะไร
ส่วนที่ 4
4) environment ใน compose file คืออะไร
`environment` คือการกำหนดตัวแปรที่ต้องการส่งเข้า container ของ service นั้นโดยตรง เขียนได้ทั้งแบบ list และ map และเป็นวิธีที่ชัดเจนว่า service นี้จะได้ env อะไรบ้างตอนรัน
ส่วนที่ 5
5) env_file คืออะไร
`env_file` คือการบอก service ให้โหลด environment variables จากไฟล์ แล้วส่งเข้า container โดยตรง เหมาะเมื่อ service มีตัวแปรจำนวนมากและไม่อยากเขียน `environment` ยาว ๆ ใน compose
ตัวอย่างนี้แปลว่าโหลดค่าจาก .env.api ก่อน แล้วกำหนด NODE_ENV ทับด้วยค่า production
ส่วนที่ 6
6) ความต่างระหว่าง .env, environment, env_file
3 วิธีนี้คล้ายกันแต่มีหน้าที่ต่างกัน ถ้าใช้ผิดบริบทมักเกิดบั๊กเรื่องค่าไม่เข้า container
| วิธี | หน้าที่หลัก | เหมาะกับกรณี |
|---|---|---|
| .env | เก็บค่าที่ใช้แทนตัวแปรใน compose (interpolation) | ต้องการใช้ `${...}` ซ้ำหลายจุด |
| environment | กำหนด env ส่งเข้า container แบบ explicit | อยากเห็นค่าชัดเจนราย service |
| env_file | โหลด env จากไฟล์เข้า container | env เยอะและอยากแยกไฟล์ต่อ service |
ส่วนที่ 7
7) ตัวอย่าง .env file
ตัวอย่างไฟล์ `.env` สำหรับบทนี้ โดยมีค่าที่เจองานจริงทั้งแอปและฐานข้อมูล
ส่วนที่ 8
8) ตัวอย่าง compose file ที่อ่านค่าจาก .env
ตัวอย่างนี้ใช้ `${...}` เพื่ออ่านค่าจาก `.env` แล้วส่งเข้า service ผ่าน `environment`
Compose จะแทน `${PORT}` `${NODE_ENV}` `${DATABASE_URL}` `${DB_USER}` `${DB_PASSWORD}` จากค่าใน .env ก่อนสร้าง service
ส่วนที่ 9
9) ตัวอย่าง compose file ที่กำหนด environment ตรง ๆ
กรณีค่าคงที่และไม่ต้องแชร์กับหลาย environment อาจกำหนดตรงใน compose ได้ทันที
ส่วนที่ 10
10) อธิบายการแทนค่า เช่น ${PORT}
Compose รองรับการแทนค่าตัวแปรด้วยรูปแบบ `${VAR}` และมี default fallback ได้ เช่น `${PORT:-3000}` ถ้าไม่เจอค่าและไม่มี fallback อาจได้ warning หรือค่าเป็นสตริงว่าง ทำให้เกิดปัญหาตอนรัน
- `${PORT}`: ต้องมีค่า ไม่งั้นเสี่ยงพัง
- `${PORT:-3000}`: ถ้าไม่ตั้งค่า จะใช้ 3000
- ค่าที่เป็นตัวเลข/boolean แนะนำใส่ quote เพื่อป้องกัน YAML แปลงชนิดเอง
ส่วนที่ 11
11) ข้อดีข้อเสียของแต่ละวิธี
เลือกวิธีให้เหมาะบริบท จะลดปัญหา config drift และทำให้ทีมดูแลต่อได้ง่าย
| วิธี | ข้อดี | ข้อเสีย |
|---|---|---|
| .env + interpolation | ลดค่าซ้ำ, เปลี่ยนค่าเป็นชุดได้เร็ว | คนเริ่มต้นมักสับสนว่า .env เข้า container อัตโนมัติ |
| environment | อ่านง่ายและชัดว่าบริการนี้ได้ค่าอะไร | ไฟล์ compose อาจยาวเมื่อมี env จำนวนมาก |
| env_file | จัดการ env จำนวนมากได้ดี แยกไฟล์เป็นระบบ | ถ้าไฟล์กระจัดกระจายมากไป จะตามค่า override ยาก |
ส่วนที่ 12
12) ข้อควรระวังเรื่อง secret และการ commit ไฟล์
`DB_PASSWORD`, API key, token และ secret อื่น ๆ ไม่ควรถูก commit ขึ้น repository แนวทางพื้นฐานที่ควรทำทันที: - ใส่ `.env` และไฟล์ secret ลง `.gitignore` - ใช้ `.env.example` สำหรับโครงคีย์ - ใน production ควรใช้ secret manager หรือ platform secret แทนการเก็บ plaintext ไว้ใน repo
- ห้ามใส่ค่า secret จริงใน README หรือเอกสารสาธารณะ
- ตรวจ diff ก่อน commit ว่าไม่มี `.env.production` หลุด
- แยก secret ออกจาก config ทั่วไปให้ชัดเจน
ส่วนที่ 13
13) ข้อผิดพลาดที่พบบ่อย
ข้อผิดพลาดเหล่านี้เกิดบ่อยในผู้เริ่มต้น และมักทำให้เข้าใจว่า Compose ไม่ทำงานทั้งที่ปัญหาคือคีย์/ชื่อไฟล์ไม่ตรง
- ลืมสร้าง `.env` ทำให้ `${PORT}` หรือ `${NODE_ENV}` ไม่ถูกแทนค่า
- ชื่อคีย์ไม่ตรงกัน เช่น compose ใช้ `${DB_USERNAME}` แต่ไฟล์มี `DB_USER`
- เข้าใจว่า `.env` จะเข้า container อัตโนมัติ ทั้งที่ไม่ได้ประกาศ `environment` หรือ `env_file`
- ใส่ path `env_file` ผิดตำแหน่ง ทำให้โหลดไฟล์ไม่เจอ
- เขียนค่า `DATABASE_URL` ชี้ host ผิด (เช่นใช้ `localhost` แทน `db` ภายใน compose)
ส่วนที่ 14
14) สถานการณ์จริงในการใช้งาน dev / test / production
แนวทางใช้งานที่พบจริงในทีมพัฒนา
| Environment | แนวทางที่แนะนำ | ตัวอย่างไฟล์/ค่า |
|---|---|---|
| dev | ใช้ `.env` ในเครื่อง + compose interpolation | NODE_ENV=development, DB_PASSWORD=dev-secret |
| test | ใช้ไฟล์เฉพาะ เช่น `.env.test` และค่า isolated | DATABASE_URL ชี้ test database |
| production | ส่งค่าจาก CI/CD หรือ secret manager | ไม่ commit `.env.production` ที่มีค่า secret จริง |
ส่วนที่ 15
15) สรุปท้ายบทแบบจำง่าย
สูตรจำเร็ว: `.env` = แหล่งค่าที่ใช้แทน `${...}` ใน compose `environment` = ค่าที่ส่งเข้า container แบบชัดเจน `env_file` = โหลด env จากไฟล์เข้า container ทีละชุด ถ้าแยกหน้าที่ 3 ตัวนี้ได้ชัด คุณจะจัดการ environment config ใน Compose ได้ถูกตั้งแต่ครั้งแรก
ประเด็นที่ 1
อย่าสับสนระหว่าง interpolation กับ env ใน container
ประเด็นที่ 2
เริ่มจากง่าย: `.env` + `environment`
ประเด็นที่ 3
env เยอะขึ้นค่อยแยก `env_file`
ประเด็นที่ 4
secret จริงห้าม commit
ส่วนที่ 16
16) แบบฝึกหัด 4 ข้อ พร้อมแนวเฉลย แบบกดแล้วค่อยเฉลย
ลองตอบเองก่อน แล้วค่อยเปิดแนวเฉลยเพื่อตรวจความเข้าใจ