이전에 포스팅한
도커를 통한 ansible 환경 배포를 진행한 적이 있었다.
그때 한번 도커를 경험해보았지만, 사실 완벽히 이해하고 사용한 것은 아니었다.
이번 시간에는 도커의 개념을 기초부터 꽉꽉 채워서 배워보겠다.
1. 컨테이너 기술의 입문
Docker란?
Docker는 애플리케이션과 그 실행에 필요한 모든 종속성을 컨테이너라는 표준화된 유닛으로 패키징하는 오픈소스 플랫폼이다.
핵심 흐름은 세 단계다:
Dockerfile → (docker build) → Docker Image → (docker run) → Docker Container
Dockerfile은 이미지를 만들기 위한 레시피다. base image, 설치할 패키지, 복사할 파일, 실행할 커맨드 등을 선언적으로 기술한다. Docker Image는 이 레시피대로 만들어진 읽기 전용 템플릿이고, Docker Container는 이미지를 실행한 인스턴스다.
OOP에 비유하면, Image는 Class이고 Container는 Instance다. 하나의 Image에서 여러 Container를 찍어낼 수 있다.
VM vs Container
VM과 컨테이너는 모두 격리된 환경을 제공하지만, 구조가 근본적으로 다르다.
| 구분 | Virtual Machine | Container |
|---|---|---|
| 격리 수준 | Hypervisor 위에 Guest OS 포함 | Host OS 커널 공유 |
| 부팅 속도 | 수십 초 ~ 수 분 | 수백 ms |
| 이미지 크기 | 수 GB (OS 포함) | 수십 MB ~ 수백 MB |
| 리소스 오버헤드 | 높음 (각 VM마다 OS 메모리 점유) | 낮음 (커널 공유) |
| 격리 강도 | 강함 (완전한 OS 분리) | 상대적으로 약함 (namespace/cgroup 기반) |
VM은 각각 Guest OS를 포함하므로 오버헤드가 크다. 컨테이너는 Host OS의 커널을 공유하면서 Linux namespace와 cgroup으로 프로세스 수준의 격리를 제공한다. 그래서 가볍고 빠르다.
단, 보안 격리 강도는 VM이 우위다. 멀티테넌트 환경에서 완전한 격리가 필요하면 VM을 선택해야 하고, 같은 팀이 운영하는 마이크로서비스들이라면 컨테이너가 합리적이다.
Docker Layer 구조
Docker Image는 여러 Layer의 스택으로 구성된다.
예를 들어 nginx 기반 웹 앱 이미지는 이런 구조다:
[web app source] ← 내 앱 코드
[nginx] ← nginx 설정
[Layer C] ← ubuntu 패키지
[Layer B] ← apt-get update
[Layer A] ← base ubuntu
각 Layer는 읽기 전용이고, Dockerfile의 각 명령어(FROM, RUN, COPY 등)가 하나의 Layer를 생성한다. 컨테이너를 실행하면 이 읽기 전용 Layer 위에 R/W Layer 하나가 얹어진다. 컨테이너 안에서 파일을 수정하면 이 R/W Layer에 기록되고, 컨테이너를 삭제하면 R/W Layer도 사라진다.
이 구조의 장점은 Layer 공유다. ubuntu Layer가 동일하면 nginx 이미지와 web app 이미지가 같은 Layer를 재사용한다. 디스크 공간도 아끼고 pull 속도도 빨라진다.
Docker Image 경로
Docker Image의 전체 경로(Full Qualified Name)는 다음과 같은 구조다:
Registry / Namespace / Image Name : Tag
| 구성 요소 | 설명 | 예시 |
|---|---|---|
| Registry | 이미지가 저장된 서버 | docker.io, ghcr.io, ECR URL |
| Namespace | 소유자 구분 (조직 또는 사용자) | library (공식), mycompany |
| Image Name | 이미지 이름 | nginx, my-app |
| Tag | 버전 | latest, 1.12.1, v2.0.0 |
공식 이미지는 docker.io/library/nginx:latest이고, 줄여서 nginx:latest로 쓴다. Private Registry를 운영하면 my-registry.com/myteam/my-app:1.0처럼 자체 경로를 사용한다.
실무에서 latest 태그는 절대 프로덕션에 쓰지 않는다. 어떤 버전이 배포되었는지 추적이 안 되기 때문이다. 반드시 명시적 버전 태그를 사용해야 한다.
2. Docker의 설치와 활용
주요 Docker CLI 명령어
Docker의 핵심 명령어들을 정리하면 다음과 같다.
| 명령어 | 설명 | 예시 |
|---|---|---|
docker pull |
Registry에서 Image 다운로드 | docker pull ubuntu:18.04 |
docker images |
로컬 Image 목록 조회 | docker images |
docker run |
컨테이너 생성 및 실행 | docker run -it --name demo1 ubuntu:18.04 /bin/bash |
docker ps |
실행 중인 컨테이너 목록 | docker ps / docker ps -a (전체) |
docker exec |
실행 중인 컨테이너에 명령 실행 | docker exec -it demo2 /bin/bash |
docker logs |
컨테이너 로그 확인 | docker logs demo3 -f |
docker stop |
컨테이너 중지 | docker stop demo3 |
docker rm |
컨테이너 삭제 | docker rm demo3 |
docker rmi |
이미지 삭제 | docker rmi ubuntu |
docker run 주요 옵션
docker run은 가장 자주 쓰는 명령어인 만큼 옵션도 다양하다. 핵심 옵션만 정리하면:
docker run -it -d --name demo2 -p 8080:80 -v /host/path:/container/path ubuntu:18.04 /bin/bash
| 옵션 | 설명 |
|---|---|
-i |
Interactive 모드. stdin을 열어둔다 |
-t |
TTY 할당. 터미널을 연결한다 |
-d |
Detach 모드. 백그라운드에서 실행한다 |
--name |
컨테이너에 이름을 부여한다 |
-p |
포트 매핑. 호스트포트:컨테이너포트 |
-v |
볼륨 마운트. 호스트경로:컨테이너경로 |
-it는 거의 세트로 쓴다. 컨테이너에 접속해서 터미널 작업을 할 때 필수다. -d는 서비스를 데몬처럼 띄울 때 사용한다. -it와 -d를 함께 쓰면 백그라운드로 실행하되 나중에 docker exec -it로 접속할 수 있는 상태가 된다.
3. Docker Image의 생성과 활용
Dockerfile 주요 명령어
Dockerfile은 Docker Image를 빌드하기 위한 스크립트다. 주요 명령어를 정리하면:
| 명령어 | 설명 | 예시 |
|---|---|---|
FROM |
Base Image 지정 | FROM ubuntu:18.04 |
RUN |
빌드 시점에 커맨드 실행 | RUN apt-get update |
COPY |
호스트 파일을 이미지로 복사 | COPY app.py /app/ |
WORKDIR |
작업 디렉토리 설정 | WORKDIR /home/demo |
ENV |
환경 변수 설정 | ENV LANG ko_KR.UTF-8 |
EXPOSE |
컨테이너 포트 선언 | EXPOSE 8080 |
CMD |
컨테이너 시작 시 실행할 명령 | CMD ["python", "app.py"] |
RUN과 CMD의 차이를 혼동하는 경우가 많다. RUN은 이미지 빌드 시점에 실행되고 Layer를 생성한다. CMD는 컨테이너 실행 시점에 실행되며, Dockerfile에서 마지막 CMD 하나만 유효하다.
Dockerfile 작성 예시
간단한 Dockerfile을 작성해보면:
# base image 설정
FROM ubuntu:18.04
# 패키지 업데이트
RUN apt-get update
# 컨테이너 시작 시 실행할 명령
CMD ["echo", "Hello FastCampus"]
이 Dockerfile로 이미지를 빌드하고 실행하는 과정:
# 이미지 빌드 (-t: 태그 지정, .: 현재 디렉토리를 빌드 컨텍스트로 사용)
docker build -t my-image:v1.0.0 .
# 빌드된 이미지 확인
docker images | grep my-image
# 컨테이너 실행
docker run my-image:v1.0.0
# 출력: Hello FastCampus
Docker Registry
Docker Image를 빌드했으면, 이를 다른 서버에서도 사용할 수 있도록 Registry에 push해야 한다.
Docker Hub가 기본 Public Registry이고, Private Registry도 직접 구축할 수 있다. AWS ECR, GCP Artifact Registry, Azure Container Registry 등 각 클라우드 벤더도 자체 Registry 서비스를 제공한다.
로컬에 Private Registry를 띄우는 것도 간단하다:
# Registry 컨테이너 실행
docker run -d -p 5000:5000 --name registry registry
# 이미지에 Registry 경로를 포함한 태그 부여
docker tag my-image:v1.0.0 localhost:5000/my-image:v1.0.0
# Registry에 push
docker push localhost:5000/my-image:v1.0.0
# Registry에 저장된 이미지 확인
curl -X GET http://localhost:5000/v2/_catalog
curl -X GET http://localhost:5000/v2/my-image/tags/list
실무에서는 CI/CD 파이프라인과 연동하여 코드 push → 이미지 빌드 → Registry push → 배포가 자동화되는 흐름을 구성한다. GitHub Actions + Docker Hub, GitLab CI + Harbor 같은 조합이 대표적이다.
실습 진행
도커를 설치하고 이미지 생성을 해보겠다.






/#으로 루트 최고권한자로 우분투에 접속되는 것을 볼 수 있다.





이제 도커파일로 이미지를 실제로 만들어보자




실행이 무사히 완료되었다!!
정리
이번 주에는 컨테이너 기술의 핵심인 Docker를 다뤘다.
- 컨테이너 vs VM: 컨테이너는 Host OS 커널을 공유하여 가볍고 빠르다. VM은 완전한 OS 격리를 제공하지만 오버헤드가 크다
- Docker의 3요소: Dockerfile(레시피) → Image(템플릿) → Container(실행 인스턴스)
- Layer 구조: 각 Dockerfile 명령이 하나의 읽기 전용 Layer를 생성하고, 컨테이너 실행 시 R/W Layer가 추가된다. Layer 공유로 디스크와 네트워크를 절약한다
- Image 경로:
Registry/Namespace/Name:Tag구조. 프로덕션에서는 반드시 명시적 태그를 사용한다 - 핵심 명령어:
pull,build,run,exec,logs,stop,rm,rmi - Dockerfile:
FROM,RUN,COPY,CMD,EXPOSE등으로 이미지 빌드를 선언적으로 정의한다 - Registry: 빌드한 이미지를 저장하고 배포하는 중앙 저장소. Docker Hub, ECR, ACR 등
다음 시간에는 Docker 컨테이너를 대규모로 관리하기 위한 오케스트레이션 도구, Kubernetes에 대해 알아본다.
'개인공부' 카테고리의 다른 글
| [Microsoft Azure] 10. 컨테이너 기술의 활용 - 클라우드 쿠버네티스 (0) | 2026.06.03 |
|---|---|
| [Microsoft Azure] 9. 컨테이너 기술의 이해 - 쿠버네티스 (1) | 2026.06.03 |
| [Microsoft Azure] 7. 서버리스 서비스의 이해 (0) | 2026.05.19 |
| [Microsoft Azure] 6. 클라우드 웹 서비스 플랫폼 (2) (0) | 2026.04.21 |
| [Microsoft Azure] 5. 클라우드 웹 서비스 플랫폼 (1) (1) | 2026.04.21 |