codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
EDU›Docker · Caddy · Cloud — 10 deploy options›Step 1

Step 1

Step 1 — Docker basics

0 views

Step 1 — Docker basics

"Works on my machine" stopped being a line thanks to Docker — package code + runtime + OS deps into one image, run anywhere.

1. Three words

  • Image — read-only template (blueprint + parts)
  • Container — running instance
  • Volume — persistent storage outside containers

One image → many containers concurrently.

2. Docker vs VM

VM Container
OS full per VM shares host kernel
Size GBs tens of MB
Start minutes seconds
Isolation strong process-level
Density low high (hundreds per server)

3. Install

# macOS / Windows
# Docker Desktop (https://www.docker.com/products/docker-desktop/)

# Linux
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

docker --version
docker run hello-world

4. First containers

docker run -it --rm alpine sh

docker run -d --name my-postgres \
  -e POSTGRES_PASSWORD=secret \
  -p 5432:5432 \
  postgres:17

docker ps
docker ps -a
docker logs -f my-postgres
docker exec -it my-postgres psql -U postgres
docker stop my-postgres
docker rm my-postgres

5. Ten useful commands

docker images
docker pull node:20-alpine
docker rmi name
docker ps -a
docker exec -it name sh
docker logs -f name
docker inspect name
docker stats
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"]

Core keywords: FROM, WORKDIR, COPY, RUN, CMD, EXPOSE, ENV, ARG.

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

7. Multi-stage build

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"]

Build tools stay in the builder stage; final image ~1/3 the size.

8. .dockerignore

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

Faster builds, smaller images, safer.

9. Volumes

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
# data preserved

docker run -v $(pwd)/data:/app/data my-app

10. Networks

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 talks to "db" by container name

docker-compose automates this.

11. Image optimization tips

  • Alpine bases (5–10MB)
  • Distroless (no shell at all)
  • Minimize layers: RUN apt-get update && apt-get install -y ...
  • Robust .dockerignore
  • COPY deps before source to preserve cache

12. Security basics

RUN addgroup -g 1001 app && adduser -D -u 1001 -G app app
USER app
  • Never bake secrets into images
  • Scan: docker scout cves my-app
  • Consider --read-only

13. Gotchas

  • Port in use — pick another host port
  • Slow builds — missing .dockerignore or bad COPY order
  • Container exits immediately — CMD not foreground (docker logs)
  • Volume permissions — UID mismatch between host user and container user
  • Disk full — docker system prune -a

14. Try it

pnpm create next-app@latest my-test
cd my-test
# add the Dockerfile above

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

Deeper

  • Docker basics note
  • Docker Compose patterns

Next

Step 2 — run several containers together with docker-compose.

Step 2 →

Step 2 — docker-compose patterns