codingstairs
노트에듀라이프연락
⌕검색⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

연락하기

로그인 없이도 보낼 수 있어요. 답변이 필요하면 이메일을 함께 적어 주세요.

  • 익명 폼으로 의견 남기기 →
  • ✉ warragon112@gmail.com
  • 카카오톡 오픈채팅 ↗

© 2026 codingstairs

  • 노트
  • 에듀
  • 검색
  • 라이프
  • 연락
  • 약관
  • RSS
  • GitHub
에듀›Docker · Caddy · 클라우드 10단계 배포 옵션›1단계

1단계

1단계 — Docker 기초

0회 조회

1단계 — Docker 기초

"내 컴퓨터에선 되는데" 가 사라진 이유 = Docker. 코드 · 런타임 · OS 의존성을 하나의 이미지 로 묶어 어디서나 똑같이 동작하게.

1. 핵심 세 단어

  • Image — 실행 가능한 템플릿 (read-only). 설계도 + 부품
  • Container — Image 를 띄운 실행 인스턴스. 실제 프로세스
  • Volume — 컨테이너 외부의 영속 저장소. DB 데이터 등

Image 하나 → Container 여러 개 (동시에 같은 이미지 여러 인스턴스).

2. Docker vs VM

가상머신 (VM) 컨테이너 (Docker)
OS 각자 전체 OS 호스트 OS 커널 공유
크기 수 GB 수십 MB
시작 시간 분 단위 초 단위
격리 강함 프로세스 수준
밀도 낮음 높음 (한 서버 수백)

3. 설치

# macOS / Windows
# Docker Desktop 공식 다운로드 (https://www.docker.com/products/docker-desktop/)

# Linux
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER   # sudo 없이 쓰려면

# 확인
docker --version
docker run hello-world

hello-world 가 뜨면 설치 완료.

4. 첫 컨테이너

# 한 번만 실행 후 종료
docker run -it --rm alpine sh
# alpine 이미지 자동 다운로드 → 컨테이너 → 셸 진입
# 종료하면 자동 삭제 (--rm)

# 백그라운드 + 포트 노출
docker run -d --name my-postgres \
  -e POSTGRES_PASSWORD=secret \
  -p 5432:5432 \
  postgres:17

# 확인
docker ps                    # 실행 중 컨테이너
docker ps -a                 # 종료된 것 포함
docker logs my-postgres      # 로그
docker logs -f my-postgres   # 로그 실시간

# 컨테이너 안으로
docker exec -it my-postgres psql -U postgres

# 중지 · 제거
docker stop my-postgres
docker rm my-postgres

5. 자주 쓰는 명령 10 개

docker images                # 이미지 목록
docker pull node:20-alpine   # 이미지 다운로드만
docker rmi 이미지이름         # 이미지 제거
docker ps -a                 # 모든 컨테이너
docker exec -it 이름 sh      # 컨테이너 안 셸
docker logs -f 이름          # 로그 실시간
docker inspect 이름          # 상세 정보 (JSON)
docker stats                 # 실시간 CPU · 메모리
docker network ls            # 네트워크 목록
docker system prune          # 사용 안 하는 리소스 정리

6. Dockerfile — 내 앱을 이미지로

FROM node:20-alpine

WORKDIR /app

# 의존성 먼저 복사 (캐시 활용)
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile

# 소스 복사 + 빌드
COPY . .
RUN pnpm build

EXPOSE 3000
CMD ["pnpm", "start"]

핵심 명령

명령 역할
FROM 베이스 이미지
WORKDIR 작업 디렉터리
COPY 파일 복사
RUN 빌드 시점 명령
CMD 컨테이너 시작 시 명령
EXPOSE 포트 문서화 (실제 노출은 -p)
ENV 환경변수
ARG 빌드 인자

빌드 + 실행

docker build -t my-app .
docker run -d -p 3000:3000 --name my-app-c my-app
curl http://localhost:3000

7. 멀티스테이지 빌드 — 이미지 1/3

# ---- 빌드 스테이지 ----
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build

# ---- 실행 스테이지 ----
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]

빌드 도구 · TypeScript · eslint 가 최종 이미지에 안 들어감. 이미지 1 GB → 300 MB 수준.

8. .dockerignore

package.json 옆에 .dockerignore:

node_modules
.next
.git
.env
.env.local
*.log
README.md
.github
.vscode

빌드 컨텍스트에서 제외. 빌드 속도 · 이미지 크기 · 보안 모두 개선.

9. 볼륨 — 데이터 영속

컨테이너는 일회성. 재시작하면 데이터 소실.

# 명명 볼륨
docker volume create pg-data
docker run -d --name pg \
  -v pg-data:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:17

# 컨테이너 삭제 후 재생성해도 데이터 유지
docker rm -f pg
docker run -d --name pg \
  -v pg-data:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:17
# → 이전 데이터 그대로

# 호스트 경로 마운트
docker run -v $(pwd)/data:/app/data my-app

10. 네트워크

# 브리지 네트워크 생성
docker network create my-net

# 같은 네트워크의 컨테이너끼리 이름으로 통신 가능
docker run -d --name db --network my-net postgres:17
docker run -d --name app --network my-net \
  -e DATABASE_URL=postgres://db:5432/... \
  my-app

# app 에서 "db" 라는 호스트명으로 접근 가능

docker-compose 가 이 패턴을 자동화.

11. 이미지 최적화 팁

  • Alpine 베이스 — 5~10MB · 단 일부 NPM 네이티브 모듈 빌드 이슈
  • Distroless (Google) — OS 셸조차 없음 · 가장 작음
  • 레이어 최소화 — RUN apt-get update && apt-get install ... 한 줄로
  • .dockerignore 철저히
  • 의존성 먼저 COPY — 소스 변경만으로 full rebuild 방지

12. 보안 기본

  • root 로 실행 금지:
    RUN addgroup -g 1001 app && adduser -D -u 1001 -G app app
    USER app
    
  • 비밀번호 · 키 — 이미지에 절대 포함 금지. 런타임 -e 또는 secret
  • 이미지 스캔 — docker scout cves my-app
  • 최소 권한 — read-only filesystem (--read-only)

13. 자주 걸리는 자리

  • 포트 충돌 — -p 3000:3000 호스트 포트 이미 사용 중
  • 이미지 빌드 매우 느림 — .dockerignore 없거나 COPY 순서 잘못
  • 컨테이너 금방 종료 — CMD 가 foreground 가 아님 · docker logs 확인
  • 권한 문제 — 볼륨 마운트 시 host user UID 와 컨테이너 user UID 불일치
  • 디스크 꽉 참 — 오래된 이미지 · 컨테이너 누적. docker system prune -a

14. 직접 해 보기

위 Dockerfile 로 작은 Next.js 앱:

pnpm create next-app@latest my-test
cd my-test

# Dockerfile 복사 + 빌드
docker build -t my-test .
docker run -d -p 3000:3000 --name my-test-c my-test
curl http://localhost:3000

# 정리
docker rm -f my-test-c
docker rmi my-test

더 깊이

  • Docker 기초 노트
  • Docker Compose 패턴 노트

다음 단계

2단계에서는 여러 컨테이너를 한 번에 띄우는 docker-compose 패턴을 배워요.

2단계 →

2단계 — docker-compose 패턴