Docker / Docker аюулгүй байдал

Docker аюулгүй байдал

Container нь тусгаарлалт үүсгэдэг ч буруу тохируулбал аюулгүй байдлын нүх үүсч болно. Энэ хичээлд production-д заавал мөрдөх дүрмүүдийг үзнэ.

Root-аар ажиллуулахгүй байх

Анхдагч байдлаар Docker container нь root хэрэглэгчээр ажиллана. Container дотор root эрхтэй байх нь аюулгүй биш:

bash
docker run -it node:20 whoami
# root   ← аюулгүй биш!

Хэрэв аппликейшнийг тасалдуулаад container дотор орвол root эрхтэй байх болно.

USER instruction

dockerfile
FROM node:20-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY dist/ ./dist/

# Тусгай хэрэглэгч үүсгэх
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Файлуудын өмчлөгчийг тохируулах
RUN chown -R appuser:appgroup /app

# Root биш хэрэглэгч болгон солих
USER appuser

EXPOSE 3000
CMD ["node", "dist/index.js"]
bash
docker run myapp whoami
# appuser   ← аюулгүй

node image-ийн бэлэн хэрэглэгч

node:20 image-д node нэртэй хэрэглэгч аль хэдийн байдаг:

dockerfile
FROM node:20-alpine

WORKDIR /app
COPY --chown=node:node package*.json ./
RUN npm ci --only=production
COPY --chown=node:node dist/ ./dist/

USER node

CMD ["node", "dist/index.js"]

--chown=node:nodeCOPY хийхэд шууд өмчлөгч тавих.

Minimal base image

Image-д байгаа бүх package нь потенциал аюулгүй байдлын нүх. Хэрэглэгдэхгүй зүйлс байхгүй байх нь дээр:

dockerfile
# ❌ Хэтэрхий том — олон шаардлагагүй хэрэгсэл
FROM ubuntu:22.04

# ✅ Зөвхөн шаардлагатай зүйл агуулсан
FROM node:20-alpine

# ✅ Хамгийн жижиг — зөвхөн compiled binary
FROM scratch

Alpine-д shell хязгаарлагдмал тул attack surface багасна.

Дистроллес image (Google):

dockerfile
FROM gcr.io/distroless/nodejs20-debian12

Shell огт байхгүй — docker exec ажиллахгүй. Production-д хамгийн аюулгүй, debugging хэцүү.

Нууц мэдээлэл зохицуулах

Dockerfile-д нууц мэдээлэл оруулахгүй

dockerfile
# ❌ Image-д орно — history-д үлдэнэ!
ENV DATABASE_URL=postgresql://user:password@db/myapp
ENV API_KEY=sk-1234567890abcdef

# ❌ Build үед нууц мэдээлэл оруулах
RUN curl -H "Authorization: Bearer hardcoded-token" https://api.example.com

Image-ийн history-г хэн ч харж болно:

bash
docker history myimage
# IMAGE layer бүрийн команд харагдана

Зөв арга: Runtime environment variable

bash
# Container ажиллуулахдаа дамжуулна
docker run -e DATABASE_URL=postgresql://... -e API_KEY=sk-... myapp
yaml
# docker-compose.yml
services:
  app:
    image: myapp
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - API_KEY=${API_KEY}
    env_file:
      - .env

.env файлыг .gitignore-д нэмнэ — Git-т ороогүй байна.

Docker secrets (Swarm)

bash
echo "mysecretpassword" | docker secret create db_password -

docker service create \
  --name myapp \
  --secret db_password \
  myimage

Container доторх /run/secrets/db_password файлаас унших.

Multi-stage build-д нууц мэдээлэл

dockerfile
# ✅ BuildKit-ийн secret mount — final image-д орохгүй
FROM node:20-alpine AS builder

RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
    npm ci
bash
docker build --secret id=npmrc,src=.npmrc .

Image scan

docker scout (орчин үеийн)

bash
# Scout суулгагдсан бол
docker scout cves myimage

# Зөвлөмж авах
docker scout recommendations myimage

Trivy (гуравдагч хэрэгсэл)

bash
# Trivy суулгах (Alpine)
docker run aquasec/trivy image myimage

# Зөвхөн HIGH, CRITICAL эмзэг байдал
docker run aquasec/trivy image --severity HIGH,CRITICAL myimage

Гаралт:

код
myimage (alpine 3.19.0)
Total: 3 (HIGH: 2, CRITICAL: 1)

┌────────────────┬────────────────┬──────────┬──────────────────┐
│    Library     │ Vulnerability  │ Severity │ Installed Version│
├────────────────┼────────────────┼──────────┼──────────────────┤
│ openssl        │ CVE-2024-0001  │ CRITICAL │ 3.1.4-r1         │
└────────────────┴────────────────┴──────────┴──────────────────┘

Read-only файл систем

Container-ийн файл системийг зөвхөн унших горимд тавих:

bash
docker run --read-only myapp
yaml
services:
  app:
    image: myapp
    read_only: true
    tmpfs:
      - /tmp # бичих шаардлагатай бол tmpfs

Capabilities хязгаарлах

Linux capabilities-ийг хязгаарлаж, зөвхөн шаардлагатайг нь үлдээнэ:

bash
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp

Аюулгүй байдлын хураангуй дүрмүүд

dockerfile
# 1. Minimal base image
FROM node:20-alpine

# 2. Root биш хэрэглэгч
RUN addgroup -S app && adduser -S app -G app
USER app

# 3. Зөвхөн шаардлагатай файл хуулах
COPY --chown=app:app dist/ ./dist/
COPY --chown=app:app package*.json ./
RUN npm ci --only=production

# 4. Нууц мэдээлэл Dockerfile-д огт байхгүй
# (runtime -e flag эсвэл env_file ашиглана)

# 5. Healthcheck
HEALTHCHECK --interval=30s CMD wget -qO- http://localhost:3000/health || exit 1

Дараагийн хичээлд:

HEALTHCHECK instruction-ийг дэлгэрэнгүй үзнэ — container эрүүл эсэхийг автоматаар шалгах.