ข้ามไปยังเนื้อหา

port และตัวแปร Environment

โดยค่าเริ่มต้น container ถูกแยกออกอย่างสมบูรณ์ — port ของตัวเองไม่สามารถเข้าถึงได้จาก host flag -p เผยแพร่ port โดยสร้าง mapping ระหว่าง port host กับ port container:

Terminal window
docker run -d -p 8080:80 nginx:alpine

รูปแบบคือ -p <host-port>:<container-port> หลังจากคำสั่งนี้ การเปิด http://localhost:8080 ใน browser จะเข้าถึง port 80 ภายใน container

คุณสามารถเผยแพร่หลาย port ได้:

Terminal window
docker run -d -p 8080:80 -p 8443:443 nginx:alpine
Terminal window
# เข้าถึงได้เฉพาะจาก localhost ไม่ใช่จากเครือข่าย
docker run -d -p 127.0.0.1:8080:80 nginx:alpine

Container อ่าน configuration จากตัวแปร environment ส่งด้วย -e:

Terminal window
docker run -d \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=myapp \
mysql:8

แต่ละ -e กำหนดตัวแปรหนึ่งตัวภายใน container

สำหรับตัวแปรจำนวนมาก เก็บไว้ในไฟล์และใช้ --env-file:

.env
MYSQL_ROOT_PASSWORD=secret
MYSQL_DATABASE=myapp
MYSQL_USER=app
MYSQL_PASSWORD=apppass
Terminal window
docker run -d --env-file .env mysql:8

วิธีนี้ช่วยให้ secret ไม่ถูกบันทึกใน shell history

การตั้งชื่อที่คาดเดาได้ให้ container ทำให้ทุกคำสั่งถัดไปง่ายขึ้น:

Terminal window
docker run -d \
--name mysite \
-p 8080:80 \
nginx:alpine

ตอนนี้คุณสามารถใช้ mysite แทน random ID ในทุกคำสั่ง docker stop, docker logs, และ docker exec

Terminal window
docker run -d \
--name webserver \
-p 8080:80 \
-e NGINX_HOST=localhost \
nginx:alpine
# ตรวจสอบ
docker ps
curl http://localhost:8080
# Run nginx with a port mapping and an env var
docker run -d \
  --name webserver \
  -p 8080:80 \
  -e NGINX_HOST=localhost \
  nginx:alpine

# Confirm the mapping
docker ps

# Fetch the default page (should return HTML)
curl -s http://localhost:8080 | head -5

# Inspect the env var inside the container
docker exec webserver env | grep NGINX

# Clean up
docker stop webserver && docker rm webserver
ตัวเลือกBenefitCost
bind เฉพาะ 127.0.0.1 (-p 127.0.0.1:8080:80)ปลอดภัยกว่า เข้าถึงได้เฉพาะจาก host เดียวกันเข้าถึงจากเครื่องอื่นในเครือข่ายไม่ได้ ต้องตั้งค่าเพิ่มถ้าจะแชร์
bind ทุก interface (-p 8080:80)เข้าถึงได้จากเครือข่ายภายนอกทันที ใช้งานง่ายเปิดกว้างเกินไป เสี่ยงถูกเข้าถึงโดยไม่ตั้งใจถ้าไม่มี firewall คุม
  • hardcode ค่า config อย่าง DB password หรือ host ไว้ใน Dockerfile ด้วย ENV แทนที่จะส่งผ่าน -e/--env-file ตอนรัน ทำให้เปลี่ยนค่าทุกครั้งต้อง build image ใหม่
  • commit ไฟล์ .env ที่มี secret จริงเข้า git แทนที่จะใช้ .env.example เป็น template
  • ลืมเผยแพร่ port ด้วย -p แล้วสงสัยว่าทำไม curl จาก host ถึงขึ้น connection refused ทั้งที่ container ทำงานปกติดี

💡 ตัวอย่างจากของจริง

Kubernetes ใช้ ConfigMap และ Secret เพื่อฉีดค่า configuration เข้า Pod ตอน runtime ที่เป็นแนวคิดเดียวกับ -e/--env-file ของ Docker เพียงแต่จัดการแบบรวมศูนย์และหมุนเวียนค่าได้ในระดับ cluster

'-p 3000:8080' หมายความว่าอะไร?
flag ใดส่งไฟล์ KEY=VALUE เป็นตัวแปร environment?
ถ้ารัน container โดยไม่มี -p สามารถเข้าถึง port จาก host ได้หรือไม่?
ประโยชน์ของการใช้ --name เมื่อรัน container คืออะไร?