[docker] 개념 정리

2025. 12. 10. 18:09·DevOps/Docker

컨테이너(Container)

컨테이너 기술은 패키징 기술이다.
애플리케이션 실행에 필요한 환경을 하나로 묶어, 어디서든 동일하게 실행되도록 만든다.

컨테이너 기술의 핵심 특징은 다음과 같다.

  1. 샌드박스화된 런타임 환경
    • 애플리케이션 프로세스가 보호된 영역에서 동작하며, 다른 프로세스에 영향을 끼치지 않는 최소 실행 환경이다.
  2. 배포가 쉬움(패키징된 환경)
    • 애플리케이션 동작에 필요한 필수 환경을 모두 포함하므로 배포가 단순하다.
  3. 운영체제(OS)로부터의 독립과 한계
    • 애플리케이션을 운영체제로부터 분리하지만, 컨테이너의 OS는 호스트 OS에 종속적이므로
      타 OS 기반 컨테이너를 그대로 구동할 수 없다.
  4. 높은 성능
    • 게스트 OS를 구동하는 오버헤드가 없기 때문에 성능이 좋다.

 컨테이너의 OS는 호스트 OS에 종속적이다.


호스트 OS에 따른 컨테이너 실행 특성

호스트 OS: Windows

  1. Windows 기반 컨테이너 구동 가능
  2. WSL을 사용하면 Linux 기반 컨테이너 구동 가능
  3. OS에 독립적인 컨테이너는 모두 구동 가능

호스트 OS: Linux

  1. Windows 기반 컨테이너 구동 불가
  2. Linux 기반 컨테이너 구동 가능
  3. OS에 독립적인 컨테이너는 모두 구동 가능

 Docker

Docker는 컨테이너 가상화 기술 기반의 오픈소스 가상화 플랫폼이다.

  • 다양한 프로그램 및 실행 환경을 컨테이너로 추상화한다.
  • 동일한 인터페이스를 제공해 프로그램 배포 및 관리가 단순해진다.

Docker의 장점

  • 이식성과 확장성이 높음
  • 오버헤드가 낮음
    • 프로세스를 격리하는 방식으로 동작하기 때문
  • 배포 및 관리가 단순함
    • 동일한 인터페이스 제공

Docker의 구동 방식(핵심 기술)

도커는 다양한 인터페이스를 통해 커널 기능을 활용한다.

  • 네임스페이스(Namespaces): 컨테이너가 독립적인 환경에서 수행될 수 있도록 분리
  • 컨트롤 그룹(cgroups): CPU/MEM 등 시스템 자원을 제한하고 할당
  • 기존에는 리눅스 커널 기능을 직접 사용했고, 0.9부터 자체 개발 엔진(libcontainer) 을 사용한다.

도커 컨테이너를 실행하기 위해서는 도커 엔진(Docker Engine) 이 필요하다.


Docker 엔진 구성 요소

도커는 크게 아래 3가지 컴포넌트로 구성된다.

  • Docker Daemon
    • 이미지, 컨테이너, 볼륨, 네트워크 등 Docker 객체를 관리한다.
  • Docker REST API Server
    • 프로그램이 도커 데몬과 통신하기 위한 API 인터페이스
  • Docker CLI
    • 사용자가 도커 명령어를 실행하는 인터페이스
    • 내부적으로 REST API를 통해 도커 데몬과 통신한다.

 Docker 아키텍처

  • 도커 클라이언트는 도커 데몬과 통신해 컨테이너를 생성/실행/배포한다.
  • 서버–클라이언트(REST API) 아키텍처 기반이며,
    • 클라이언트/서버가 같은 시스템에 설치될 수도 있고
    • 다른 시스템에 설치될 수도 있다.
  • 도커 호스트에서 동작하는 도커 데몬은 레지스트리로부터 이미지를 다운로드하고 인스턴스를 생성한다.

Docker 객체(Docker Objects)

도커에서 다루는 객체는 대표적으로 다음과 같다.

  • Docker Image
  • Docker Container
  • Docker Network
  • Docker Volume

Docker Daemon

  • 클라이언트가 Docker API로 요청하는 내용을 처리하며 Docker 오브젝트를 관리한다.
  • 도커 서비스를 위해 도커 호스트의 다른 데몬과 통신하기도 한다.

Docker Client

  • 사용자가 도커와 통신하는 방법 중 하나다.
  • 도커 관련 명령어를 도커 데몬에 요청한다.

Docker Registry

  • 도커 이미지 저장소(퍼블릭 저장소)
  • 대표적으로 Docker Hub가 있다.

Docker Container

  • 이미지를 실행하면 생성된다.

Docker Image

  • 컨테이너 실행에 필요한 파일과 설정값을 포함한다.
  • 이미지는 보통 레지스트리(Docker Hub)에서 내려받아 사용하며, 직접 구축할 수도 있다.
  • 등록된 이미지를 베이스로 라이브러리를 추가 설치한 커스텀 이미지를 생성해 사용한다.
  • 이미지를 만들기 위해 Dockerfile을 사용한다.

Dockerfile

  • 베이스 이미지 선택
  • 추가 패키지 설치
  • 이미지 구동 시 수행할 작업 선택

 Docker의 기반 기술

  • 도커는 Go 언어로 개발되었다.
  • 리눅스 커널이 제공하는 다음 기술을 활용한다.
    • 네임스페이스(Namespaces)
    • 컨트롤 그룹(cgroups)
    • 유니온 파일 시스템(Union File System)

기술 정리

  • 네임스페이스: 컨테이너에게 독립된 공간 제공
  • 컨트롤 그룹: 컨테이너가 사용할 CPU/MEM 등의 자원을 제어
  • 유니온 파일 시스템: 서로 다른 파일 시스템을 하나의 디렉토리에 마운트해 논리적으로 하나처럼 보여줌

Docker 이미지 = SHA256로 생성된 값

  • Read-only template
  • 컨테이너 실행에 필요한 파일과 설정값 포함
  • 컨테이너 구동 중 추가/변경은 이미지가 아니라 컨테이너에 저장됨
  • 레이어 기반으로 구성됨
  • 이미지는 레이어 리스트를 가지고 있음
    → 도커 엔진이 레이어를 참조해 컨테이너 파일 시스템을 구성
# 이미지를 구성하는 레이어 리스트 확인 예시
dive nginx
  • 하나의 레이어는 다수의 이미지에 공통으로 사용될 수 있다.
    → 즉, 하나의 이미지로 여러 컨테이너 생성 가능

레이어(Layer)

  • 상위 레이어는 하위 레이어에 의존성을 가진다.
  • 각 레이어는 읽기 전용이다.
  • 컨테이너 생성 시 최상위 계층에 쓰기 가능한 레이어가 생성된다.
  • 최상위 계층 내용이 하위 내용과 다르면 최상위 내용이 덮어쓰기 된다.
  • 도커 이미지 빌드 시 하위 이미지와의 차이를 새로운 레이어로 생성해 기록한다.
  • 레이어는 순차적으로 쌓이는 방식이다.
  • 레이어 ID는 SHA256 기반 16진수 해시 값이다.
  • SHA256 비교로 레이어 변경 여부를 탐지할 수 있다.
# 레이어 확인 예시 (nginx pull 후 확인)
docker inspect nginx
  • 레이어 ID와 디렉토리 이름은 일치하지 않을 수 있다.
  • 일반적으로 레이어 저장 위치는 다음과 같다.
    • /var/lib/docker/<storage-driver>

Container Layer = Writable Layer

  • 컨테이너 생성 시 쓰기 가능한 thin R/W layer가 최상위에 생성된다.
  • 컨테이너 실행 중 생성/변경된 데이터는 Container Layer에 저장된다.
  • 컨테이너 삭제 시 Container Layer의 내용도 함께 삭제된다.
  1. 볼륨 마운트: 로컬 파일 시스템과 컨테이너 파일 시스템 동기화
  2. export: 컨테이너 이미지 + Container Layer 내용을 새로운 이미지로 저장
docker inspect [NAMES]
# NAMES: 컨테이너 이름
  • Storage Driver가 레이어 저장/관리와 Writable layer 저장을 담당한다.
  • LowerDir: 이미지의 read-only 레이어들
  • UpperDir: 컨테이너 변경사항이 기록되는 writable layer
  • MergedDir: 두 레이어를 합쳐 하나의 파일 시스템처럼 보여주는 마운트 포인트
  • WorkDir: atomic action 보장을 위해 임시로 파일을 준비하는 경로
docker logs <컨테이너이름>

Storage Driver

  • 도커는 레이어 관리 및 Writable layer 저장을 위해 storage driver를 사용한다.
  • 플러그인 방식으로 다양한 드라이버가 있다.
    • overlay2, fuse-overlayfs, btrfs, zfs, vfs 등
  • 현재 사용하는 드라이버를 교체(plug-out/plug-in)할 수 있다.

 Docker 명령어

systemctl status docker
sudo usermod -aG docker $USER

컨테이너 실행(run)

docker container run [option] image[:tag] [command] [args...]

옵션

  • -d : 백그라운드 모드
  • -p : 호스트 ↔ 컨테이너 포트 연결(포트 포워딩/포트 매핑)
  • -v : 호스트 ↔ 컨테이너 디렉토리 연결(마운트)
  • -e : 환경변수 설정
  • --name : 이름 설정
  • --rm : 종료 시 컨테이너 자동 제거
  • -it : 터미널 접속( -i + -t )

태그(tag)

  • 이미지 버전

command/args

  • 컨테이너 구동 후 실행할 명령/인자

docker container run ubuntu:16.04
# 실행할 명령어가 없어서 컨테이너가 실행 직후 종료된다.
docker container run -it ubuntu:16.04 /bin/bash
# 인터랙티브 터미널로 접속하여 bash 실행 → 프로세스가 유지되므로 종료되지 않음
# bash 종료 시 실행할 프로세스가 없으면 컨테이너도 종료됨

docker container run -d -p 3306:3306 -e \
MYSQL_ALLOW_EMPTY_PASSWORD=true --name mysql57 mysql:5.7
  • MySQL 5.7 이미지로 컨테이너 실행
  • 백그라운드(-d)
  • 포트 매핑(-p 호스트3306:컨테이너3306)
  • 환경변수(-e ...)
  • 이름 설정(--name mysql57)

docker container run -v $PWD:/usr/share/nginx/html -d -p 54321:80 nginx
  • Nginx 컨테이너 실행 + 볼륨 공유
  • 호스트의 현재 디렉토리를 Nginx의 웹 루트에 마운트

리소스 모니터링 / 제한

docker stats [container name] --no-stream
# --no-stream 제거 시 실시간 모니터링
docker update --memory 500m --memory-swap -1 [names]
# --memory 500m: 메모리 500MB로 제한
# --memory-swap -1: swap 한계를 무제한으로 설정
grep -c processor /proc/cpuinfo
# VM 호스트에 할당된 CPU 수 확인
docker run --rm -it -d [--cpuset-cpus=2,3] [--cpus 1] --name=stress \
progrium/stress --cpu 4 --timeout 20s
  • --cpuset-cpus=2,3 : CPU 2,3번 코어만 사용 제한
  • --cpus 1 : CPU 사용률 제한(코어 수 기준 비율로 동작)

컨테이너 볼륨 마운트 / export-import

docker container run -it ubuntu /bin/bash
docker container run -it -v $PWD:/tmp/msg ubuntu /bin/bash
# 호스트의 현재 디렉토리를 컨테이너 /tmp/msg에 마운트
# 컨테이너에서 만든 파일은 호스트 디렉토리에 남아서 컨테이너 삭제 후에도 유지됨
docker export [컨테이너이름] > ./myubuntu.tar
docker import myubuntu.tar myubuntu:latest
docker run -it myubuntu /bin/bash
# 컨테이너 레이어에 저장된 내용이 유지됨

 Docker SDK

컨테이너 실행시키기 (Python)

import docker

client = docker.from_env()
print("<Running a container>")

container = client.containers.run("nginx", detach=True)
print(container.id)
print(container.logs())

Dockerfile

커스텀 도커 이미지를 생성하기 위한 도구다.

  • 베이스 이미지
  • 설치 패키지
  • 실행할 애플리케이션
  • 환경 변수
  • 포트 등
    컨테이너 생성에 필요한 작업을 지시자(Directive) 로 지정한다.

지시자(Directive)

  • FROM: 베이스 이미지 지정
  • WORKDIR: 작업 디렉토리 지정
  • COPY: 컨테이너에 복사할 파일 지정
  • RUN: 설치할 패키지 지정
  • EXPOSE: 컨테이너에서 오픈할 포트(메타데이터)
  • ENV: 환경 변수 지정
  • CMD: 컨테이너 시작 시 실행 커맨드

 

도커 파일 실행 방법

FROM python:2.7-slim
#베이스 이미지를 설정

WORKDIR /app
#작업 디렉토리 지정
COPY . /app
#복사할 파일 지정
RUN pip install --trusted-host pypi.python.orf -r requirements.txt
#설치할 패키지 지정
EXPOSE 80
#컨테이너에서 외부로 오픈할 포트 지정
ENV NAME World
#환경변수 지정
CMD ["python","app.py"]
#실행되는 커맨드 지정

위 도커 파일을 작성한 후, 실행할 app.py와 requirements.txt 도 작성.

이때 requirements.txt는 웹 서비스 구동에 필요한 추가 라이브러리와 프레임워크를 적는다. _ 종속성

host='0.0.0.0’ - 외부에서 접근 가능하게 모든 IP 주소에 대해 열어줌 (도커 컨테이너에서 필수)

port=80 - 서버를 80번 포트에서 실행함 (HTTP 기본 포트)

설정 위치 의미 실제로 포트를 여나?

EXPOSE <포트> 도커 이미지에 기록만 하는 메타데이터 (설명서 느낌) ❌ 안 열림
app.run(port=XX) 애플리케이션이 컨테이너 내부에서 실제로 리스닝하는 포트 ✅ 열림
docker run -p 호스트포트:컨테이너포트 호스트 ↔ 컨테이너 통신을 위해 포트를 연결 ✅ 열림 (외부와 연결됨)
docker build --tag=freindlyhello . 

현재 디렉토리에 있는 Dockerfile과 그 안에서 참조하는 파일들을 기준으로 Docker 이미지를 빌드하고, 이름은 freindlyhello로 붙이는 것

docker run -p 4000:80 freindlyhello

-p 는 옵션 중 포워딩을 의미

컨테이너 외부에서 외부포트로 접속하는 요청을 내부포트로 전달하는 것임.

Flask가 컨테이너 안에서 80번 포트에서 실행되고 있음.

  • 컨테이너: 0.0.0.0:80에서 Flask 서버 동작 중
  • 호스트(로컬): localhost:4000 → 내부 컨테이너의 80포트로 트래픽 전달됨

도커 이미지 공유하기

리포지터리에 업로드하기 전 이미지 태깅이 필요함!

docker tag [기존_이미지명] [새로운_이름(:태그)]

도커 허브(Docker Hub) 또는 레지스트리 에 푸시(push) 하기 위해 이미지에 정해진 네이밍 규칙에 따라 "이름:태그"를 지정하는 것!

 


 Docker Compose

Docker Compose는 단일 서버에서 다수의 컨테이너를 하나의 서비스로 정의하고 묶음으로 관리하는 도구다.

  • 서비스를 구성하는 여러 컨테이너를
  • 하나의 설정 파일과 하나의 명령으로
  • 생성/실행/종료/삭제까지 제어할 수 있다.

이를 위해 docker-compose.yml(compose file) 설정 파일을 사용한다.

 

  • simplified control
    • 하나의 설정 파일을 통해 다수의 컨테이너를 설정하고 관리하고 제어할 수 있다.
  • efficient collaboration
    • 설정 파일은 관리와 공유가 쉬워, 팀 내부의 효과적 협업을 용이하게 한다.
  • rapid application development
    • 도커 컴포즈는 configuration cache 가 가능하며, 이를 통해 신속한 서비스 재시작이 가능하다.
  • portabillity across enviroment
    • 도커 컴포즈는 설정 파일에서 변수를 사용할 수 있어, 이를 통해 다양한 환경 사용자등에게 동적으로 특화된 환경을 구성할 수 있다.
  • extensive community and support
    • 도커 컴포즈 커뮤니티가 활성화 되어 있어, 폭 넓은 사용자로부터 다양한 지원을 받을 수 있다.

compose.yml 실행하는 방법

services:
  web:  # Flask 애플리케이션을 위한 서비스
    build: . #현재 디렉토리에 있는 Dockerfile을 기준으로 Flask용 이미지 빌드
    ports:
      - "8000:5000" 
      #호스트의 8000번 포트 → 컨테이너의 5000번 포트에 연결
      #브라우저에서 http://localhost:8000으로 접근 가능
    develop:
      watch:
        - action: sync
          path: .
          target: /code

  redis:  # Redis 서버를 위한 서비스
    image: "redis:alpine" #redis:alpine 이미지를 사용해서 Redis 서버 실행
    #별도로 빌드 안 하고 도커 허브에서 가져옴

 

 

컨테이너가 2개 생성된 것을 볼 수 있음.

web: 직접 build: . 로 이미지 생성함 → 이미지 1개 생성

redis:alpine 이미 도커 허브에 있는 이미지고,만든 게 아니니까 맨 밑에 뜨는게 보임

 

'DevOps > Docker' 카테고리의 다른 글

[Docker compose - Postgres 설정] 부팅 이슈 해결하기 (Internship : Infra)  (0) 2026.01.20
[docker-compose]온프렘 도커 배포 실전 삽질기 (네트워크, 쿠키, 헬스체크 해결편)  (0) 2025.12.31
[docker-compose]온프레미스 환경에서 Docker Compose로 서비스 구성하기  (0) 2025.12.31
[Docker] 실행 방법  (0) 2025.12.11
[BuildX & 서버 이전] FastAPI + PaddleOCR 서버 이전기: "exec format error"와 Docker Buildx 완벽 가이드  (0) 2025.12.07
'DevOps/Docker' 카테고리의 다른 글
  • [docker-compose]온프렘 도커 배포 실전 삽질기 (네트워크, 쿠키, 헬스체크 해결편)
  • [docker-compose]온프레미스 환경에서 Docker Compose로 서비스 구성하기
  • [Docker] 실행 방법
  • [BuildX & 서버 이전] FastAPI + PaddleOCR 서버 이전기: "exec format error"와 Docker Buildx 완벽 가이드
yeseul-kim01
yeseul-kim01
  • yeseul-kim01
    슬 개발일지
    yeseul-kim01
  • 전체
    오늘
    어제
    • 분류 전체보기 (79)
      • 자격증 (1)
        • 정보보안기사 (0)
      • DevOps (17)
        • Docker (6)
        • Kubernetes (1)
        • GitHub Actions (0)
        • AWS (4)
        • Monitoring (1)
        • Nginx (1)
        • GCP (3)
      • ServerDev (34)
        • SpringBoot (13)
        • DJango (5)
        • FastAPI (14)
        • Next (0)
        • Flask (0)
        • Database (2)
      • Algorithm (2)
        • BFS (0)
        • DFS (1)
        • 다익스트라 (0)
      • CS (8)
      • Data Engineering (1)
      • AI&MLOps (2)
      • Architecture (6)
      • Software Engineering (0)
        • Library Packaging (0)
      • Project (5)
        • docx-generator (0)
        • speak-note (2)
        • ms-serving (1)
        • keyshield (2)
      • ProgrammingLanguages (3)
        • Python (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    di
    아키텍처설계
    KeyShield
    FastAPI - CORS 마스터
    SpeakNote
    multipartfile
    트러블슈팅
    프로젝트기록-speaknote
    SpringBoot
    Kubernetes
    Django
    grpc
    실무일기-인프라편
    비동기처리
    MLops
    rag
    실무일기-백엔드편
    KServe
    depends
    실시간시스템
    멀티모듈
    FastAPI
    docker
    백엔드
    아키텍처
    하이브리드아키텍처
    동시성제어
    프로젝트기록-KeyShield
    STT
    NLP부트캠프
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
yeseul-kim01
[docker] 개념 정리
상단으로

티스토리툴바