Dockerfile

Dockerfile

1. Dockerfile์ด๋ž€?

Dockerfile์€ Docker ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์„ค์ • ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. ํ…์ŠคํŠธ ํŒŒ์ผ์— ๋ช…๋ น์–ด๋ฅผ ์ž‘์„ฑํ•˜๋ฉด Docker๊ฐ€ ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰ํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

Dockerfile โ†’ docker build โ†’ Docker Image โ†’ docker run โ†’ Container
(์„ค๊ณ„๋„)       (๋นŒ๋“œ)        (ํ…œํ”Œ๋ฆฟ)        (์‹คํ–‰)      (์ธ์Šคํ„ด์Šค)

์™œ Dockerfile์„ ์‚ฌ์šฉํ• ๊นŒ์š”?

์žฅ์  ์„ค๋ช…
์žฌํ˜„์„ฑ ๋™์ผํ•œ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ˜๋ณต ์ƒ์„ฑ
์ž๋™ํ™” ์ˆ˜๋™ ์„ค์ • ๋ถˆํ•„์š”
๋ฒ„์ „ ๊ด€๋ฆฌ Git์œผ๋กœ ์ด๋ ฅ ์ถ”์ 
๋ฌธ์„œํ™” ํ™˜๊ฒฝ ์„ค์ •์ด ์ฝ”๋“œ๋กœ ๊ธฐ๋ก

2. Dockerfile ๊ธฐ๋ณธ ๋ฌธ๋ฒ•

๊ธฐ๋ณธ ๊ตฌ์กฐ

# ์ฃผ์„
๋ช…๋ น์–ด ์ธ์ž

์ฃผ์š” ๋ช…๋ น์–ด

๋ช…๋ น์–ด ์„ค๋ช… ์˜ˆ์‹œ
FROM ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€ FROM node:18
WORKDIR ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ WORKDIR /app
COPY ํŒŒ์ผ ๋ณต์‚ฌ COPY . .
RUN ๋นŒ๋“œ ์‹œ ๋ช…๋ น ์‹คํ–‰ RUN npm install
CMD ์ปจํ…Œ์ด๋„ˆ ์‹œ์ž‘ ๋ช…๋ น CMD ["npm", "start"]
EXPOSE ํฌํŠธ ๋…ธ์ถœ EXPOSE 3000
ENV ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ENV NODE_ENV=production

3. ๋ช…๋ น์–ด ์ƒ์„ธ ์„ค๋ช…

FROM - ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€

๋ชจ๋“  Dockerfile์€ FROM์œผ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

# ๊ธฐ๋ณธ
FROM ubuntu:22.04

# Node.js ์ด๋ฏธ์ง€
FROM node:18

# ๊ฒฝ๋Ÿ‰ Alpine ์ด๋ฏธ์ง€ (๊ถŒ์žฅ)
FROM node:18-alpine

# ๋ฉ€ํ‹ฐ ์Šคํ…Œ์ด์ง€ ๋นŒ๋“œ
FROM node:18 AS builder
FROM nginx:alpine AS production

WORKDIR - ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ

์ดํ›„ ๋ช…๋ น์–ด๊ฐ€ ์‹คํ–‰๋  ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

WORKDIR /app

# ์ดํ›„ ๋ช…๋ น์–ด๋Š” /app์—์„œ ์‹คํ–‰
COPY . .          # /app์œผ๋กœ ๋ณต์‚ฌ
RUN npm install   # /app์—์„œ ์‹คํ–‰

COPY - ํŒŒ์ผ ๋ณต์‚ฌ

ํ˜ธ์ŠคํŠธ์˜ ํŒŒ์ผ์„ ์ด๋ฏธ์ง€๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.

# ํŒŒ์ผ ๋ณต์‚ฌ
COPY package.json .

# ๋””๋ ‰ํ† ๋ฆฌ ๋ณต์‚ฌ
COPY src/ ./src/

# ๋ชจ๋“  ํŒŒ์ผ ๋ณต์‚ฌ
COPY . .

# ์—ฌ๋Ÿฌ ํŒŒ์ผ ๋ณต์‚ฌ
COPY package.json package-lock.json ./

ADD vs COPY

# COPY: ๋‹จ์ˆœ ๋ณต์‚ฌ (๊ถŒ์žฅ)
COPY local-file.txt /app/

# ADD: URL ๋‹ค์šด๋กœ๋“œ, ์••์ถ• ํ•ด์ œ ๊ฐ€๋Šฅ
ADD https://example.com/file.tar.gz /app/
ADD archive.tar.gz /app/  # ์ž๋™ ์••์ถ• ํ•ด์ œ

RUN - ๋นŒ๋“œ ์‹œ ๋ช…๋ น ์‹คํ–‰

์ด๋ฏธ์ง€ ๋นŒ๋“œ ์ค‘์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

# ๊ธฐ๋ณธ
RUN npm install

# ์—ฌ๋Ÿฌ ๋ช…๋ น์–ด (๋ ˆ์ด์–ด ์ตœ์ ํ™”)
RUN apt-get update && \
    apt-get install -y curl && \
    rm -rf /var/lib/apt/lists/*

# ์บ์‹œ ํ™œ์šฉ์„ ์œ„ํ•œ ๋ถ„๋ฆฌ
COPY package*.json ./
RUN npm install
COPY . .

CMD - ์ปจํ…Œ์ด๋„ˆ ์‹œ์ž‘ ๋ช…๋ น

์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

# exec ํ˜•์‹ (๊ถŒ์žฅ)
CMD ["npm", "start"]
CMD ["node", "app.js"]

# shell ํ˜•์‹
CMD npm start

ENTRYPOINT vs CMD

# ENTRYPOINT: ํ•ญ์ƒ ์‹คํ–‰ (๋ณ€๊ฒฝ ์–ด๋ ค์›€)
ENTRYPOINT ["node"]
CMD ["app.js"]
# ์‹คํ–‰: node app.js

# docker run myimage other.js
# ์‹คํ–‰: node other.js (CMD๋งŒ ๋ณ€๊ฒฝ๋จ)

ENV - ํ™˜๊ฒฝ ๋ณ€์ˆ˜

# ๋‹จ์ผ ๋ณ€์ˆ˜
ENV NODE_ENV=production

# ์—ฌ๋Ÿฌ ๋ณ€์ˆ˜
ENV NODE_ENV=production \
    PORT=3000 \
    DB_HOST=localhost

EXPOSE - ํฌํŠธ ๋ฌธ์„œํ™”

# ํฌํŠธ ๋…ธ์ถœ (๋ฌธ์„œ ๋ชฉ์ , ์‹ค์ œ ๋งคํ•‘์€ -p ์˜ต์…˜)
EXPOSE 3000
EXPOSE 80 443

ARG - ๋นŒ๋“œ ์‹œ ๋ณ€์ˆ˜

# ๋นŒ๋“œ ์‹œ ์ „๋‹ฌ๋ฐ›๋Š” ๋ณ€์ˆ˜
ARG NODE_VERSION=18
FROM node:${NODE_VERSION}

ARG APP_VERSION=1.0.0
ENV APP_VERSION=${APP_VERSION}
# ๋นŒ๋“œ ์‹œ ๊ฐ’ ์ „๋‹ฌ
docker build --build-arg NODE_VERSION=20 .

4. ์‹ค์Šต ์˜ˆ์ œ

์˜ˆ์ œ 1: Node.js ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ:

my-node-app/
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ package.json
โ””โ”€โ”€ app.js

package.json:

{
  "name": "my-node-app",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}

app.js:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.json({ message: 'Hello from Docker!', version: '1.0.0' });
});

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Dockerfile:

# ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€
FROM node:18-alpine

# ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ •
WORKDIR /app

# ์˜์กด์„ฑ ํŒŒ์ผ ๋ณต์‚ฌ (์บ์‹œ ํ™œ์šฉ)
COPY package*.json ./

# ์˜์กด์„ฑ ์„ค์น˜
RUN npm install

# ์†Œ์Šค ์ฝ”๋“œ ๋ณต์‚ฌ
COPY . .

# ํฌํŠธ ๋…ธ์ถœ
EXPOSE 3000

# ์‹คํ–‰ ๋ช…๋ น
CMD ["npm", "start"]

๋นŒ๋“œ ๋ฐ ์‹คํ–‰:

# ์ด๋ฏธ์ง€ ๋นŒ๋“œ
docker build -t my-node-app .

# ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰
docker run -d -p 3000:3000 --name node-app my-node-app

# ํ…Œ์ŠคํŠธ
curl http://localhost:3000

# ์ •๋ฆฌ
docker rm -f node-app

์˜ˆ์ œ 2: Python Flask ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ:

my-flask-app/
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ requirements.txt
โ””โ”€โ”€ app.py

requirements.txt:

flask==3.0.0
gunicorn==21.2.0

app.py:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/')
def hello():
    return jsonify(message='Hello from Flask in Docker!')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Dockerfile:

FROM python:3.11-slim

WORKDIR /app

# ์˜์กด์„ฑ ์„ค์น˜
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# ์†Œ์Šค ๋ณต์‚ฌ
COPY . .

EXPOSE 5000

# Gunicorn์œผ๋กœ ์‹คํ–‰ (ํ”„๋กœ๋•์…˜)
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]

๋นŒ๋“œ ๋ฐ ์‹คํ–‰:

docker build -t my-flask-app .
docker run -d -p 5000:5000 my-flask-app
curl http://localhost:5000

์˜ˆ์ œ 3: ์ •์  ์›น์‚ฌ์ดํŠธ (Nginx)

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ:

my-website/
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ nginx.conf
โ””โ”€โ”€ public/
    โ””โ”€โ”€ index.html

public/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>My Docker Website</title>
</head>
<body>
    <h1>Hello from Nginx in Docker!</h1>
</body>
</html>

Dockerfile:

FROM nginx:alpine

# ์ปค์Šคํ…€ ์„ค์ • ๋ณต์‚ฌ (์„ ํƒ์‚ฌํ•ญ)
# COPY nginx.conf /etc/nginx/nginx.conf

# ์ •์  ํŒŒ์ผ ๋ณต์‚ฌ
COPY public/ /usr/share/nginx/html/

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

5. ๋ฉ€ํ‹ฐ ์Šคํ…Œ์ด์ง€ ๋นŒ๋“œ

๋นŒ๋“œ ํ™˜๊ฒฝ๊ณผ ์‹คํ–‰ ํ™˜๊ฒฝ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ด๋ฏธ์ง€ ํฌ๊ธฐ๋ฅผ ์ค„์ž…๋‹ˆ๋‹ค.

React ์•ฑ ์˜ˆ์‹œ

# Stage 1: ๋นŒ๋“œ
FROM node:18-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Stage 2: ์‹คํ–‰ (nginx๋กœ ์„œ๋น™)
FROM nginx:alpine

COPY --from=builder /app/build /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Go ์•ฑ ์˜ˆ์‹œ

# Stage 1: ๋นŒ๋“œ
FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY . .
RUN go build -o main .

# Stage 2: ์‹คํ–‰ (์ตœ์†Œ ์ด๋ฏธ์ง€)
FROM alpine:latest

WORKDIR /app
COPY --from=builder /app/main .

EXPOSE 8080
CMD ["./main"]

ํฌ๊ธฐ ๋น„๊ต:

golang:1.21-alpine  โ†’  ์•ฝ 300MB (๋นŒ๋“œ ํ™˜๊ฒฝ)
์ตœ์ข… ์ด๋ฏธ์ง€         โ†’  ์•ฝ 15MB (์‹คํ–‰ ํ™˜๊ฒฝ)

6. ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค

.dockerignore ํŒŒ์ผ

๋ถˆํ•„์š”ํ•œ ํŒŒ์ผ์„ ๋นŒ๋“œ์—์„œ ์ œ์™ธํ•ฉ๋‹ˆ๋‹ค.

# .dockerignore
node_modules
npm-debug.log
.git
.gitignore
.env
*.md
Dockerfile
.dockerignore

๋ ˆ์ด์–ด ์ตœ์ ํ™”

# ๋‚˜์œ ์˜ˆ: ๋งค๋ฒˆ ์ „์ฒด ์žฌ์„ค์น˜
COPY . .
RUN npm install

# ์ข‹์€ ์˜ˆ: package.json ๋ณ€๊ฒฝ ์‹œ๋งŒ ์žฌ์„ค์น˜
COPY package*.json ./
RUN npm install
COPY . .

์ž‘์€ ์ด๋ฏธ์ง€ ์‚ฌ์šฉ

# ํฌ๊ธฐ ํผ
FROM node:18           # ~1GB

# ๊ถŒ์žฅ
FROM node:18-alpine    # ~175MB

# ์ตœ์†Œ
FROM node:18-slim      # ~200MB

๋ณด์•ˆ

# ๋ฃจํŠธ๊ฐ€ ์•„๋‹Œ ์‚ฌ์šฉ์ž๋กœ ์‹คํ–‰
FROM node:18-alpine

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

WORKDIR /app
COPY --chown=appuser:appgroup . .

7. ์ด๋ฏธ์ง€ ๋นŒ๋“œ ๋ช…๋ น์–ด

# ๊ธฐ๋ณธ ๋นŒ๋“œ
docker build -t ์ด๋ฏธ์ง€๋ช… .

# ํƒœ๊ทธ ์ง€์ •
docker build -t myapp:1.0 .

# ๋‹ค๋ฅธ Dockerfile ์‚ฌ์šฉ
docker build -f Dockerfile.prod -t myapp:prod .

# ๋นŒ๋“œ ์ธ์ž ์ „๋‹ฌ
docker build --build-arg NODE_ENV=production -t myapp .

# ์บ์‹œ ์—†์ด ๋นŒ๋“œ
docker build --no-cache -t myapp .

# ๋นŒ๋“œ ๊ณผ์ • ์ƒ์„ธ ์ถœ๋ ฅ
docker build --progress=plain -t myapp .

๋ช…๋ น์–ด ์š”์•ฝ

Dockerfile ๋ช…๋ น์–ด ์„ค๋ช…
FROM ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€ ์ง€์ •
WORKDIR ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ •
COPY ํŒŒ์ผ/๋””๋ ‰ํ† ๋ฆฌ ๋ณต์‚ฌ
RUN ๋นŒ๋“œ ์‹œ ๋ช…๋ น ์‹คํ–‰
CMD ์ปจํ…Œ์ด๋„ˆ ์‹œ์ž‘ ๋ช…๋ น
EXPOSE ํฌํŠธ ๋ฌธ์„œํ™”
ENV ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •
ARG ๋นŒ๋“œ ์‹œ ๋ณ€์ˆ˜
ENTRYPOINT ๊ณ ์ • ์‹คํ–‰ ๋ช…๋ น

๋‹ค์Œ ๋‹จ๊ณ„

04_Docker_Compose.md์—์„œ ์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•จ๊ป˜ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ด…์‹œ๋‹ค!

to navigate between lessons