Docker란 무엇이고 개발자가 배워야 하는 이유는?
개발자를 위한 Docker 실용 가이드: 컨테이너 vs VM, 핵심 명령어, Dockerfile, 그리고 실제 프로젝트에서 시작하는 방법.
Docker는 채용 공고와 설정 가이드에서 계속 나타나는데, 컨테이너를 다뤄본 적 없다면 실제 코드를 작성하기 전에 넘어야 할 벽처럼 느껴질 수 있다. 어휘만 넘어가면 그리 복잡하지 않다.
컨테이너가 실제로 무엇인지
컨테이너는 애플리케이션을 실행하는 데 필요한 모든 것을 패키징한다: 코드, 런타임, 시스템 라이브러리, 설정 파일. 가상 머신이 아니다. VM은 커널을 포함한 전체 운영 체제를 가상화하므로 부팅하는 데 1분이 걸릴 수 있고 몇 기가바이트의 RAM을 먹는다. 컨테이너는 호스트 머신의 커널을 공유하고 프로세스만 격리하므로 1초 이내에 시작되고 보통 기가바이트가 아닌 수십 메가바이트를 사용한다.
이 차이가 Docker가 로컬 개발과 CI 파이프라인을 빠르게 장악한 이유다. 한 대의 노트북에서 Postgres 데이터베이스, Redis 캐시, 앱 서버를 OS에 직접 설치하지 않고도 띄울 수 있다.
알아야 할 핵심 요소
매일 다루는 대부분을 다루는 네 가지 용어가 있다:
- Image: Dockerfile에서 빌드된 읽기 전용 템플릿. 파일시스템의 스냅샷과 그것을 실행하는 방법에 대한 메타데이터라고 생각하면 된다.
- Container: 이미지의 실행 중인 인스턴스. 컨테이너를 시작, 중지, 삭제할 수 있으며 이미지는 건드리지 않아도 된다.
- Dockerfile: 이미지를 빌드하는 명령어를 한 줄씩 담은 텍스트 파일.
- Registry: 이미지를 저장하고 가져오는 곳. 보통 Docker Hub다.
Node.js 앱을 위한 최소한의 Dockerfile은 다음과 같다:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
docker build -t my-app .로 빌드하고 docker run -p 3000:3000 my-app으로 실행한다. -p 플래그는 머신의 포트를 컨테이너 내 포트에 매핑하므로 브라우저에서 앱에 접근할 수 있다.
자주 쓸 명령어
자주 쓰는 명령어는 몇 가지로 대부분을 커버한다:
docker ps— 실행 중인 컨테이너 나열docker ps -a— 중지된 것을 포함한 모든 컨테이너 나열docker images— 머신의 이미지 나열docker logs <container>— 실행 중이거나 충돌한 컨테이너의 출력 확인docker exec -it <container> sh— 실행 중인 컨테이너 내 셸 열기docker rm/docker rmi— 더 이상 필요 없는 컨테이너와 이미지 정리
마지막 명령어 쌍이 예상보다 중요하다. Docker는 기꺼이 디스크 공간을 오래된 이미지와 중지된 컨테이너에 빼앗기게 놔둔다. 가끔 docker system prune을 실행하면 놀랍도록 많은 공간을 회수할 수 있다.
docker-compose가 워크플로우를 바꾸는 이유
대부분의 실제 프로젝트는 한 개 이상의 컨테이너가 필요하다: 앱 서버, 데이터베이스, 아마도 캐시. 각각에 대해 docker run 명령어를 작성하는 것은 금방 지루해진다. docker-compose.yml은 전체 스택을 한 파일에서 정의할 수 있게 한다:
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: devpassword
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
docker compose up을 실행하면 두 서비스가 함께 시작되고, 서로 연결되어 web이 서비스 이름으로 db에 접근할 수 있다. 거의 모든 오픈 소스 저장소의 README에서 이런 설정을 볼 수 있으며, 이를 이해하면 프로젝트를 클론해서 수동으로 Postgres, Redis 등을 설치하는 대신 몇 분 안에 실행할 수 있다.
초기에 많은 사람이 헷갈리는 부분
볼륨은 처음엔 거의 모든 사람을 헷갈리게 한다. 볼륨이 없으면 컨테이너 내 작성된 모든 것은 컨테이너가 제거될 때 사라지므로 데이터베이스에는 문제가 된다. 위의 compose 파일에 있는 volumes 섹션은 명시된 볼륨을 컨테이너 내 경로에 매핑하므로 데이터가 재시작 후에도 유지된다.
또 다른 흔한 실수는 .dockerignore 파일이 없어서 node_modules이나 .git을 이미지에 복사하는 것이다. .gitignore처럼 추가한다:
node_modules
.git
.env
이렇게 하면 빌드가 빠르고 이미지가 작아지므로 이미지를 레지스트리에 푸시하거나 Kubernetes에 배포할 때 중요하다.
기본 개념 이후 갈 곳
컨테이너 빌드와 실행이 자연스러워지면 다음 유용한 기술은 더 작은 프로덕션 이미지를 위한 다단계 빌드, Docker 네트워킹 모드 이해, 연결이 제대로 안 될 때 docker inspect 출력 읽기다. 어려운 것은 없고, 처음엔 단지 낯설 뿐이다.
실제 애플리케이션 컨테이너화와 클라우드 배포 파이프라인 연결에 대한 자세한 내용은 Korra Studio의 DevOps와 Cloud 섹션을 확인해보자.
AI 도움을 받아 작성했으며, Michal Pilch(CISSP), Korra Studio에서 검토 및 게시했어요.
이것은 Korra Studio 나레지베이스의 한 노트예요. 플랫폼은 모든 주제를 1-to-1 멘토링과 함께 제공해요.
무료로 시작하기arrow_forward