목차
![]() |
![]() |
컨테이너의 역사
![]() |
![]() |
[컨테이너 인터널 #1] 컨테이너 톺아보기 - https://tech.kakaoenterprise.com/154
도커없이 컨테이너 만들기 - https://netpple.github.io/docs/make-container-without-docker/
컨테이너 역사: chroot부터 Kubernetes까지 - http://www.opennaru.com/openshift/container/history-of-the-container/
2.1 도커 이미지와 컨테이너
A container image is a standardized package that includes all of the files, binaries, libraries, and configurations to run a container.
컨테이너 이미지는 컨테이너를 실행하는 데 필요한 모든 파일(바이너리, 라이브러리 및 구성)을 포함하는 표준화된 패키지입니다.

https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-an-image/
2.2 도커 컨테이너 다루기
run

https://docs.docker.com/reference/cli/docker/container/run
claude3.7 을 통한 docker run 옵션 정리
Docker run 명령어 옵션 분류
- 컨테이너 식별 및 기본 설정
- 리소스 관리
- 네트워킹
- 스토리지 및 파일시스템
- 보안 및 격리
- 프로세스 제어
- 환경 및 설정
- 하드웨어 및 디바이스
- 로깅 및 모니터링
1. 컨테이너 식별 및 기본 설정
--name | 컨테이너에 이름 할당 |
--cidfile | 컨테이너 ID를 파일에 저장 |
--rm | 컨테이너 종료 시 자동 제거 |
--restart | 컨테이너 재시작 정책 설정 (no, always, on-failure, unless-stopped) |
--init | 컨테이너 내에 init 프로세스 사용 |
2. 리소스 관리
-m, --memory | 메모리 제한 설정 |
--memory-swap | 스왑 메모리 제한 설정 |
--cpus | 컨테이너가 사용할 CPU 수 지정 |
-c, --cpu-shares | CPU 공유 비율 설정 |
--cpu-period, --cpu-quota | CPU CFS 주기 및 할당량 제한 |
--cpuset-cpus | 실행 가능한 CPU 지정 (0-3, 0,1) |
--blkio-weight | 블록 I/O 상대적 가중치 설정 (10-1000) |
--pids-limit | 프로세스 수 제한 설정 |
--ulimit | Ulimit 옵션 설정 |
3. 네트워킹
--network | 컨테이너를 네트워크에 연결 |
-p, --publish | 컨테이너 포트를 호스트에 매핑 |
-P, --publish-all | 모든 노출된 포트를 랜덤 포트에 매핑 |
--add-host | 컨테이너 hosts 파일에 항목 추가 |
--dns | 사용자 정의 DNS 서버 설정 |
--dns-search | 사용자 정의 DNS 검색 도메인 설정 |
--ip, --ip6 | IPv4/IPv6 주소 지정 |
--mac-address | 컨테이너 MAC 주소 지정 |
--expose | 포트 또는 포트 범위 노출 |
4. 스토리지 및 파일시스템
-v, --volume | 볼륨 마운트 |
--mount | 파일시스템 마운트 설정 |
--tmpfs | tmpfs 디렉토리 마운트 |
-w, --workdir | 컨테이너 내부 작업 디렉토리 설정 |
--storage-opt | 컨테이너 스토리지 드라이버 옵션 |
--volumes-from | 지정된 컨테이너의 볼륨 마운트 |
--read-only | 컨테이너 루트 파일시스템을 읽기 전용으로 마운트 |
5. 보안 및 격리
--security-opt | 보안 옵션 설정 |
--privileged | 컨테이너에 확장 권한 부여 |
--pid | 사용할 PID 네임스페이스 |
--userns | 사용할 사용자 네임스페이스 |
--uts | 사용할 UTS 네임스페이스 |
--ipc | 사용할 IPC 모드 |
--isolation | 컨테이너 격리 기술 (Windows에서 유용) |
--cap-add, --cap-drop | Linux 기능 추가 또는 제거 |
--no-new-privileges | 권한 상승 방지 |
6. 프로세스 제어
-d, --detach | 백그라운드에서 컨테이너 실행 |
--detach-keys | 컨테이너 분리 키 시퀀스 재정의 |
-a, --attach | STDIN, STDOUT, STDERR에 연결 |
-i, --interactive | 연결되지 않아도 STDIN 유지 |
-t, --tty | 의사 TTY 할당 |
--sig-proxy | 수신된 신호를 프로세스에 프록시 |
7. 환경 및 설정
-e, --env | 환경 변수 설정 |
--env-file | 환경 변수 파일에서 읽기 |
-l, --label | 컨테이너에 메타데이터 설정 |
--label-file | 레이블 파일에서 읽기 |
--entrypoint | 이미지의 기본 ENTRYPOINT 재정의 |
--hostname, -h | 컨테이너 호스트 이름 |
--domainname | 컨테이너 NIS 도메인 이름 |
--sysctl | 네임스페이스 커널 파라미터 설정 |
8. 하드웨어 및 디바이스
--device | 호스트 디바이스를 컨테이너에 추가 |
--device-cgroup-rule | cgroup 허용 디바이스 목록에 규칙 추가 |
--gpus | GPU 디바이스를 컨테이너에 추가 |
--device-read-bps, --device-write-bps | 디바이스 읽기/쓰기 속도 제한 |
--device-read-iops, --device-write-iops | 디바이스 읽기/쓰기 IOPS 제한 |
9. 로깅 및 모니터링
--log-driver | 컨테이너 로깅 드라이버 |
--log-opt | 로그 드라이버 옵션 |
--health-cmd | 상태 확인을 실행할 명령 |
--health-interval | 상태 확인 간격 |
--health-retries | 비정상으로 보고하기 위한 연속 실패 횟수 |
--health-timeout | 상태 확인 타임아웃 |
--health-start-period | 상태 확인 재시도 카운트다운 시작 전 초기화 기간 |
--stop-signal | 컨테이너를 중지하는 신호 |
--stop-timeout | 컨테이너를 강제 종료하기 전 대기 시간(초) |
docker network
브리지(bridge), 호스트(host), 논(none), 컨테이너(container), 오버레이(overlay)
서드파티 솔루션 - weave, flannel,openvswitch
https://yeongki0944.tistory.com/150
출처 : Docker Networking Model — Introduction - https://hwchiu.medium.com/docker-networking-model-introduction-194a2a2c9b68
None |
Host |
Bridge |
Bridge - Default Behaviors |
Container |
MacVLAN

97. [Docker + Network] Docker 컨테이너의 Macvlan 사용해보기 - https://blog.naver.com/alice_k106/220984112963
도입 시기: 2016년 Docker 1.12에서 공식적으로
도입 목적: 컨테이너에 물리적 네트워크와 동일한 서브넷에서 고유 IP 주소 부여, 직접 네트워크 연결 가능

https://github.com/moby/moby/releases?expanded=true&page=1&q=macvlan
항목 | [docker0 브릿지 구조] |
[MacVLAN 구조] |
구조 | ![]() |
![]() |
도입시기 | 도커 초기 | 도커 1.12부터 정식 도입 |
네트워크 구조 | 컨테이너의 veth - 호스트의 docker0 브릿지와 연결 | 호스트 물리 NIC에서 직접 여러 서브 인터페이스 생성 |
네트워크 주소 | 컨테이너는 호스트와 다른 서브넷 사용 | 컨테이너가 물리 네트워크와 동일한 서브넷 사용 |
호스트-컨테이너 통신 | 가능 | 불가능 |
컨테이너간 통신 | 가능 | 가능 |
네트워크 성능 |
상대적으로 낮은 Throughput (초당 22기가) | 상대적으로 높은 Throughput (초당 27기가) |
![]() |
![]() |
|
출처 : https://blog.naver.com/alice_k106/220984112963 | ||
CPU성능 | 상대적으로 높은 사용률 | 상대적으로 낮은 사용률 |
구성 복잡성 | 간단 | 복잡 (부모 인터페이스 설정 작업 필요) |
안정성 | 호스트와 독립적 운영 | 부모 인터페이스 장애시 모든 서브넷 인터페이스도 중단 |
MacVLAN에서 호스트와 컨테이너 간 통신이 불가능한 이유
브릿지: 리눅스 커널 netfilter 기반으로 작동 > netfilter를 통해 호스트-컨테이너 간 통신이 가능
MacVLAN: 리눅스 커널에 동일 물리 인터페이스 내 다른 MAC 주소 간 직접 통신 기능이 구현되어 있지 않아 호스트-컨테이너 간 통신이 불가능
MacVLAN을 사용할 때 호스트와 컨테이너 간 통신이 불가능한 이유는 MacVLAN의 근본적인 설계 방식 때문입니다:
- Bridge 모드 네트워크 설계 - MacVLAN의 Bridge 모드는 컨테이너 간 통신만 허용하고 호스트-컨테이너 간 통신은 허용하지 않도록 설계되었습니다.
- 서브 인터페이스 구조 - 호스트의 물리적 네트워크 카드에서 서브 인터페이스를 생성하여 컨테이너에 직접 연결하는 방식이며, 이 서브 인터페이스들은 부모 인터페이스(호스트)와 통신하도록 설계되지 않았습니다.
- 별도의 MAC 주소 - 각 컨테이너는 고유한 MAC 주소를 가지며 물리적 네트워크에 직접 연결된 것처럼 동작합니다. 이는 컨테이너와 호스트가 네트워크 관점에서 별개의 장치처럼 동작하게 만들어 서로 직접 통신할 수 없습니다.
- 네트워크 분리 목적 - MacVLAN은 컨테이너를 물리 네트워크에 직접 연결해 높은 성능을 제공하는 것이 주 목적이며, 호스트와의 통신 제한은 네트워크 분리와 보안 강화를 위한 의도적 설계입니다.
이미지에 나와 있듯이 "MacVLAN 네트워크를 사용하는 컨테이너는 기본적으로 호스트와 통신이 불가능합니다. 위 예에서 컨테이너A는 서버 2와는 통신할 수 있지만, 서버 1과는 통신할 수 없습니다."
외부 라우터나 네트워크 경로를 통해 "밖으로 나갔다 들어오는" 방식으로는 호스트와 컨테이너 간 통신이 가능합니다. 이것은 MacVLAN의 직접 통신 제한을 우회하는 방법입니다.
가능한 시나리오:
- 외부 라우터를 통한 우회 통신:
- 컨테이너의 패킷이 물리 네트워크로 나가서
- 외부 라우터가 이를 다시 동일 호스트의 IP로 라우팅
- 이 경우 직접 통신은 아니지만 결과적으로 호스트-컨테이너 통신 가능
- 추가 네트워크 인터페이스 사용:
- 호스트에 여러 네트워크 인터페이스가 있는 경우
- MacVLAN이 설정되지 않은 다른 인터페이스를 통해 통신 가능
이 방식은 직접적인 내부 통신이 아니라 실제로 물리 네트워크를 통과하는 형태이므로, 추가적인 네트워크 장비나 설정이 필요하며 일반적인 사용 사례에서는 권장되지 않을 수 있습니다.
MacVLAN을 사용하면서 호스트와 통신이 필요한 경우, 일반적으로는 다른 네트워크 드라이버(bridge 등)를 추가로 구성하는 것이 더 간단한 해결책입니다.
docker volume
# 볼륨 생성 docker volume create my-volume # 생성된 볼륨 목록 확인 docker volume ls # 특정 볼륨 상세 정보 확인 docker volume inspect my-volume
![]() |
|
# 볼륨을 마운트하여 nginx 컨테이너 실행 docker run -d --name nginx-test -v my-volume:/usr/share/nginx/html -p 80:80 nginx # 컨테이너 내부에서 볼륨 확인 docker exec -it nginx-test bash cd /usr/share/nginx/html echo "Hello Docker Volume" > index.html exit # 다른 컨테이너에서 같은 볼륨 사용하기 docker run -d --name nginx-test2 -v my-volume:/usr/share/nginx/html -p 8080:80 nginx # 브라우저에서 http://localhost:8080 접속하면 "Hello Docker Volume" 확인 가능


# Docker 볼륨 위치 확인 sudo ls -la /var/lib/docker/volumes/ # 특정 볼륨 데이터 확인 sudo ls -la /var/lib/docker/volumes/my-volume/_data/ # inspect명령어로 Mountpoint 확인 docker volume inspect my-volume | grep Mountpoint
![]() |
|
docker logging
도커의 로깅 드라이버 : json-file(default)
도커 컨테이너의 로그는 Host(Linux)에 저장
max-size : 로그파일의 최대크기
max-file : 로그파일의 개수








첫 번째 섹션
<source> @type forward </source>
- <source> 태그는 Fluentd가 데이터를 어디서 받을지 정의
- @type forward는 TCP 소켓을 통해 다른 Fluentd 인스턴스로부터 로그를 수신한다는 의미
- forward 입력 플러그인은 Fluentd의 기본 전송 프로토콜을 사용
두 번째 섹션:
<match docker.*> @type mongo database nginx collection access host 192.168.0.102 port 27017 flush_interval 10s </match>
- <match docker.*>는 태그가 "docker."로 시작하는 모든 로그 이벤트에 적용되는 규칙을 정의합니다.
- @type mongo는 이 로그들을 MongoDB로 보낸다는 의미입니다.
- database nginx와 collection access는 데이터가 저장될 MongoDB의 데이터베이스와 컬렉션을 지정합니다.
- host 192.168.0.102와 port 27017은 MongoDB 서버의 위치를 지정합니다.
- flush_interval 10s는 로그 데이터를 10초마다 MongoDB로 전송한다는 의미입니다.
즉, 이 설정은 다른 Fluentd 인스턴스로부터 로그를 수신하고, "docker."로 시작하는 태그가 있는 로그를 192.168.0.102:27017에 있는 MongoDB의 nginx 데이터베이스의 access 컬렉션에 10초마다 저장하도록 구성되어 있습니다.
Docker 컨테이너 디렉토리 파일 설명표
파일/디렉토리명 | 유형 | 설명 |
[container-id]-json.log | 로그 파일 | • 컨테이너 stdout/stderr 로그 저장 • JSON 형식(타임스탬프, 스트림 타입, 메시지 포함) • 로그 드라이버 설정에 따라 크기 제한/로테이션 가능 |
config.v2.json | 설정 파일 | • 컨테이너 핵심 구성 정보 • 이미지, 명령어, 환경변수, 작업 디렉토리 정보 • 컨테이너 메타데이터(이름, 생성시간, 상태) |
hostconfig.json | 설정 파일 | • 호스트 시스템 연결 구성 • 리소스 제한(CPU, 메모리), 포트 매핑 • 볼륨 마운트, 네트워크 모드, 보안 설정 |
hostname | 네트워크 파일 | • 컨테이너 호스트명 • 컨테이너 내부 /etc/hostname에 매핑 |
hosts | 네트워크 파일 | • 컨테이너 내부 /etc/hosts 내용 • 호스트명-IP 주소 매핑 정보 |
resolv.conf | 네트워크 파일 | • DNS 설정 파일 • 컨테이너가 사용할 네임서버 정보 |
resolv.conf.hash | 네트워크 파일 | • 설정 파일 무결성 검증용 해시값 • 변경 사항 감지에 사용 |
checkpoints/ | 디렉토리 | • 컨테이너 상태 저장 지점(스냅샷) • 체크포인트 기능 사용 시 활용 |
mounts/ | 디렉토리 | • 볼륨 마운트 정보 • 바인드 마운트, 볼륨 마운트 연결 정보 |
Docker 명령어와 JSON 파일 관계
명령어 | 사용하는 파일 | 용도 |
docker inspect | config.v2.json, hostconfig.json | 컨테이너 상세 정보 조회 (내부적으로 이 파일들 참조) |
docker ps | config.v2.json | 컨테이너 상태, 이름, 명령어 정보 표시 |
docker stats | config.v2.json | 컨테이너 리소스 모니터링 |
docker logs | config.v2.json (LogPath 정보) | 로그 파일 위치 참조 |
docker restart | 모든 설정 파일 | 컨테이너 재시작 시 설정 로드 |
docker update | hostconfig.json | 컨테이너 리소스 제한 등 설정 업데이트 |
docker exec | config.v2.json | 실행 중인 컨테이너 식별 및 접근 |

container 리소스 할당
옵션 | 설명 | 예시 | 기본값 |
--cpu-shares | CPU 사용 비율을 상대적으로 설정(가중치). CPU 경합 시 비율에 따라 할당됨. |
--cpu-shares=512 | 1024 |
--cpuset-cpus | 컨테이너가 사용할 특정 CPU 코어 지정 | --cpuset-cpus="0,2" (0번, 2번 코어 사용) --cpuset-cpus="0-3" (0~3번 코어 사용) |
모든 코어 |
--cpu-period | CFS(Completely Fair Scheduler) 주기 설정 (마이크로초 단위) | --cpu-period=100000 | 100,000 (100ms) |
--cpu-quota | CFS 주기 내에서 컨테이너가 사용할 수 있는 CPU 시간 (마이크로초 단위) | --cpu-quota=50000 (50% CPU 사용) | -1 (무제한) |
--cpus | 컨테이너가 사용할 CPU 개수를 직접 지정 | --cpus=1.5 (1.5개 코어 사용) | - |
--memory | 컨테이너가 사용할 수 있는 최대 메모리 양 | --memory=1g (1GB) --memory=512m (512MB) |
- (호스트의 메모리 제한 없음) |
--memory-swap | 컨테이너가 사용할 수 있는 메모리+스왑 총량 | --memory=1g --memory-swap=2g (1GB 메모리 + 1GB 스왑) |
메모리의 2배 |
--memory-reservation | 메모리 소프트 제한 (경합 시 이 값으로 조정) | --memory-reservation=750m | - |
--memory-swappiness | 컨테이너의 메모리 스왑 성향 설정 (0~100) | --memory-swappiness=0 (최대한 스왑 안 함) | 호스트 설정 사용 |
--oom-kill-disable | 메모리 부족 시 OOM Killer에 의한 종료 방지 | --oom-kill-disable=true | false |
상세 설명
- --cpu-shares: 상대적 가중치로, 컨테이너 간 CPU 경합이 있을 때만 의미가 있음. 절대적 CPU 제한이 아닌 비율 개념.
- --cpuset-cpus: 특정 작업이 특정 코어에서 실행되어야 할 때 유용 (NUMA 아키텍처 등).
- --cpu-period와 --cpu-quota: 함께 사용하여 CFS에서 CPU 사용량을 정밀하게 제어 (예: --cpu-period=100000 --cpu-quota=50000은 CPU 50% 제한).
- --cpus: 위의 period와 quota를 더 간단하게 표현한 방식 (내부적으로는 동일하게 작동).
- --memory: 하드 제한으로, 초과 시 OOM Killer가 프로세스를 종료시킬 수 있음.
- --memory-swap: (메모리 + 스왑) 총량을 의미. --memory와 동일하게 설정하면 스왑 사용 안 함.






100,000(cpu period) 중 25,000(cpu-quota)만큼 할당 > CPU주기 1/4 제한 > CPU성능 1/4 정도로 감소
컨테이너의 CPU 할당시간 = [--cpu-quota] / [--cpu-period]

--cpus 는 " 컨테이너의 CPU 할당시간 = [--cpu-quota] / [--cpu-period] " 해당 수식을 직관적으로 지정하는 옵션

Block I/O 제한
옵션 | 설명 | 예시 | 기본값 |
--device-write-bps | 특정 디바이스에 대한 쓰기 속도(bytes per second) 제한 | --device-write-bps /dev/sda:1mb (초당 1MB로 제한) |
제한 없음 |
--device-read-bps | 특정 디바이스에 대한 읽기 속도(bytes per second) 제한 | --device-read-bps /dev/sda:10mb (초당 10MB로 제한) |
제한 없음 |
--device-read-iops | 특정 디바이스에 대한 초당 읽기 작업 수(I/O operations per second) 제한 | --device-read-iops /dev/sda:1000 (초당 1000회 읽기 작업) |
제한 없음 |
--device-write-iops | 특정 디바이스에 대한 초당 쓰기 작업 수(I/O operations per second) 제한 | --device-write-iops /dev/sda:500 (초당 500회 쓰기 작업) |
제한 없음 |
- BPS(Bytes Per Second): 디스크에서 초당 전송할 수 있는 바이트 수를 제한하며, 대역폭 제어에 사용됨
- IOPS(I/O Operations Per Second): 초당 수행할 수 있는 I/O 작업 횟수를 제한
- 모든 제한은 특정 장치(/dev/sda 등)에 대해 개별적으로 적용됨
- 단위는 b(바이트), k(킬로바이트), m(메가바이트), g(기가바이트) 사용 가능


2.3 도커 이미지
학습주제
도커 storage layer, 스토리지 드라이브, aufs 드라이버, CoW, RoW, Devicemapper, OverlayFS, Btrfs, ZFS, Overlay2


2.4 Dockerfile

도커파일(Dockerfile) 명령어 요약표
명령어 설명 예시
명령어 | 설명 | 예시 |
FROM | 베이스 이미지 지정 | FROM ubuntu:20.04 FROM python:3.9-slim |
MAINTAINER | 이미지 작성자 정보 (deprecated) | MAINTAINER John Doe <john@example.com> |
LABEL | 메타데이터 추가 | LABEL version="1.0" LABEL maintainer="info@example.com" LABEL description="웹 서버 이미지" |
RUN | 명령 실행 및 레이어 생성 | RUN apt-get update && apt-get install -y nginx RUN pip install flask |
ADD | 파일/디렉터리 추가(URLs, 압축파일 지원) | ADD app.tar.gz /app ADD https://example.com/file.txt /data/ |
WORKDIR | 작업 디렉터리 설정 | WORKDIR /app WORKDIR /var/www/html |
EXPOSE | 컨테이너 포트 노출 | EXPOSE 80 EXPOSE 8080/tcp 8081/udp |
CMD | 컨테이너 시작 명령 지정 | CMD ["nginx", "-g", "daemon off;"] CMD ["python", "app.py"] |
COPY | 파일/디렉터리 복사 | COPY . /app COPY package.json /app/ |
ENV | 환경변수 설정 | ENV NODE_ENV production ENV PATH /usr/local/bin:$PATH |
VOLUME | 볼륨 마운트 포인트 지정 | VOLUME /data VOLUME ["/var/log", "/var/db"] |
ARG | 빌드 타임 변수 정의 | ARG VERSION=latest ARG BUILD_DATE |
USER | 실행 사용자 지정 | USER nginx USER 1000:1000 |
ENTRYPOINT | 컨테이너 시작점 지정 | ENTRYPOINT ["nginx", "-g", "daemon off;"] ENTRYPOINT ["java", "-jar"] |
- FROM: 모든 Dockerfile은 FROM으로 시작해야 함. 다단계 빌드 시 여러 FROM 사용 가능.
- MAINTAINER: 더 이상 사용을 권장하지 않음. LABEL로 대체 권장.
- LABEL: 키-값 쌍 형태로 메타데이터 저장. 이미지에 버전, 작성자, 설명 등 정보 추가. 여러 LABEL 사용 가능.
- RUN: 이미지 빌드 중 실행되는 명령어. 각 RUN은 새 레이어를 생성하므로 명령어 체인(&& 사용)으로 레이어 수 최소화 권장.
- ADD: 압축 파일 자동 해제. 원격 URL에서 파일 다운로드 가능. 단순 복사는 COPY 권장.
- WORKDIR: 이후 명령어(RUN, CMD, ENTRYPOINT, COPY, ADD)의 작업 디렉터리 지정. 없는 디렉터리는 자동 생성.
- EXPOSE: 문서화 목적으로 컨테이너가 사용하는 포트 표시. 실제 포트 게시는 안 됨. 실행 시 -p 옵션 필요.
- CMD: 컨테이너 실행 시 기본 명령. Dockerfile에 하나만 유효. docker run 인자로 덮어쓸 수 있음.
- COPY: 로컬 파일만 복사 가능. 기능이 단순하여 ADD보다 권장됨.
- ENV: 빌드 및 실행 시간에 사용 가능한 환경변수 설정. 컨테이너 내부에서도 유지됨.
- VOLUME: 데이터 영속성을 위한 마운트 포인트 선언. 호스트 경로는 런타임에 지정.
- ARG: 빌드 시에만 사용 가능한 변수 정의. docker build --build-arg로 전달. ENV와 달리 컨테이너 실행 시 유지되지 않음.
- USER: 이후 명령(RUN, CMD, ENTRYPOINT)의 실행 사용자 지정. 이름 또는 UID:GID 형식 사용 가능.
- ENTRYPOINT: 컨테이너가 실행될 때 항상 실행되는 명령. CMD와 함께 사용 시 CMD는 인자로 전달됨.
명령어 사용 모범 사례
- 다단계 빌드 활용: 빌드 도구와 런타임 환경 분리로 이미지 크기 축소
- 레이어 최소화: RUN 명령어 체인으로 레이어 수 줄이기 (&&, \ 사용)
- .dockerignore 사용: 불필요한 파일 제외하여 빌드 컨텍스트 최적화
- Alpine 기반 이미지 사용: 이미지 크기 최소화
- 비 루트 사용자 사용: 보안 강화를 위해 USER 명령어로 권한 제한
- CMD와 ENTRYPOINT 조합: ENTRYPOINT는 기본 명령, CMD는 기본 인자로 활용


도커 빌드 컨텍스트 개념과 실습
빌드 컨텍스트 기본 개념
빌드 컨텍스트(Build Context)는 도커 이미지를 빌드할 때 도커 데몬에게 전송되는 파일들의 집합입니다. docker build 명령어를 실행할 때 지정하는 디렉토리나 URL이 빌드 컨텍스트가 됩니다.
docker build -t myimage:1.0 . # 여기서 '.'은 현재 디렉토리를 빌드 컨텍스트로 지정
빌드 컨텍스트 작동 방식
- 컨텍스트 전송: docker build 명령을 실행하면, 지정된 컨텍스트의 모든 파일과 하위 디렉토리가 .dockerignore에 정의된 예외를 제외하고 도커 데몬에 전송됩니다.
- 전송 프로세스: 빌드 컨텍스트는 압축(tar)되어 도커 데몬에 전송됩니다. 이는 로컬에서 빌드하더라도 마찬가지입니다.
- 빌드 단계: 도커 데몬은 전송받은 컨텍스트와 Dockerfile을 사용하여 이미지를 빌드합니다.
실습으로 확인한 결과
방금 실행한 디버깅용 Dockerfile을 통해 확인한 실제 빌드 컨텍스트에 포함된 파일 목록:
./.dockerignore ./Dockerfile ./Dockerfile.debug ./Dockerfile.list ./config.json ./src/app.js
원래 디렉토리에 있었던 파일들 중 아래 파일들이 제외되었음을 확인할 수 있습니다:
- README.md (.dockerignore의 *.md 패턴과 일치)
- logs/ 디렉토리와 logs/app.log (.dockerignore의 logs 패턴과 일치)
- temp-file.txt (.dockerignore의 temp-* 패턴과 일치)
컨텍스트 데이터의 성격
빌드 컨텍스트는 단순한 파일 목록이 아닌 실제 파일 내용을 포함합니다. 도커 데몬은 다음을 전송받습니다:
- 파일 메타데이터: 파일 이름, 경로, 권한, 타임스탬프 등
- 파일 내용: 실제 파일의 모든 바이트 데이터
- 디렉토리 구조: 폴더 계층 구조
이는 실습에서 확인한 빌드 컨텍스트 크기(7.68KB)가 단순한 파일 이름 목록보다 큰 이유를 설명합니다. 이 크기는 모든 파일 내용과 메타데이터를 포함합니다.
빌드 컨텍스트와 Dockerfile 명령어의 관계
- COPY와 ADD: 이 명령어들은 빌드 컨텍스트 내의 파일만 이미지에 추가할 수 있습니다.
- COPY ./src/app.js /app/ # 빌드 컨텍스트의 파일만 복사 가능
- 상대 경로: Dockerfile의 모든 상대 경로는 빌드 컨텍스트를 기준으로 합니다.
- 컨텍스트 외부 접근 불가: COPY ../outside_file /app/ 같은 명령은 실패합니다. 빌드 컨텍스트 외부 파일에 접근할 수 없습니다.
빌드 컨텍스트 최적화하기
- .dockerignore 사용: 불필요한 파일 제외
- # .dockerignore 예시 node_modules .git *.log
- 컨텍스트 크기 최소화: 필요한 파일만 포함하여 빌드 속도 향상
- 전용 빌드 디렉토리: 필요한 파일만 있는 별도 디렉토리를 컨텍스트로 사용
- 다단계 빌드: 빌드 도구와 런타임 환경 분리로 효율성 향상
주의사항
- 대용량 컨텍스트: 큰 파일이 포함되면 빌드 속도가 느려집니다.
- 루트 디렉토리 사용 금지: 루트(/)를 컨텍스트로 사용하면 전체 파일 시스템이 전송됩니다.
- 민감한 정보 제외: 보안 키, 인증 정보 등은 .dockerignore로 제외해야 합니다.
빌드 컨텍스트를 이해하고 최적화하면 도커 이미지 빌드 과정이 더 효율적이고 안전해집니다.
# 테스트 디렉토리 생성 mkdir docker-context-test cd docker-context-test # 소스 코드 디렉토리 및 파일 생성 mkdir src echo 'console.log("Hello from app.js");' > src/app.js # 로그 파일 (빌드에 불필요) mkdir logs echo "test log data" > logs/app.log # 설정 파일 echo '{"name": "docker-test"}' > config.json # README 파일 (제외될 예정) echo '# Docker Context Test' > README.md # 임시 파일 (제외될 예정) echo "temporary data" > temp-file.txt # 기본 Dockerfile 생성 cat > Dockerfile << EOF FROM node:14-alpine WORKDIR /app COPY . . CMD ["node", "src/app.js"] EOF # .dockerignore 파일 생성 cat > .dockerignore << EOF logs *.md temp-* EOF
# BuildKit 비활성화하고 빌드 컨텍스트 크기 확인 DOCKER_BUILDKIT=0 docker build -t myapp:1.0 . 2>&1 | grep "Sending build context"
# 로컬 디렉토리 내용 확인 # 현재 디렉토리 모든 파일 확인 (빌드 컨텍스트 전) find . -type f | sort # 또는 tar 명령으로 확인 tar -czf - . | tar -tzf - | sort
# 디버깅용 Dockerfile 생성 cat > Dockerfile.debug << EOF FROM alpine WORKDIR /context COPY . . RUN find . -type f | sort CMD ["echo", "Done"] EOF # BuildKit 비활성화하고 빌드하여 컨텍스트 내용 확인 DOCKER_BUILDKIT=0 docker build -f Dockerfile.debug -t context-debug .

캐시를 이용한 이미지 빌드



멀티 스테이지 빌드는 하나의 Dockerfile 안에 여러개의 FROM 이미지를 정의함으로써 빌드완료시 최종적으로 생성될 이미지의 크기를 줄이는 역할


Onbuild, Stopsignal, Healthcheckm Shell
2.5 도커 데몬

dockerd H- unix:///var/run/docker.sock > sock 통신
srw-rw---- 1 root docker 0 [날짜] /var/run/docker.sock sudo usermod -aG docker $USER

데몬에 tls 보안
스토리지 드라이버의 원리
CoW, Row


도커 스토리지 원리: CoW 및 RoW 기술 분석
1. 도커 스토리지 아키텍처 기본 개념
도커의 스토리지 관리는 계층화된 이미지 시스템을 통해 이루어집니다. 도커는 스토리지 드라이버를 사용하여 이러한 계층화된 파일시스템을 관리합니다. 스토리지 드라이버의 핵심 기능은 다음과 같습니다:
- 읽기 전용 레이어를 쌓아서 컨테이너 이미지 구성
- 컨테이너 실행 시 쓰기 가능한 레이어 추가
- 효율적인 스토리지 사용을 위한 데이터 관리 최적화
도커가 사용하는 주요 스토리지 드라이버는 OverlayFS, DeviceMapper, BTRFS, ZFS, VFS 등이 있으며, 이들은 모두 CoW(Copy-on-Write) 또는 RoW(Redirect-on-Write) 메커니즘을 구현합니다.
2. Copy-on-Write (CoW) 메커니즘
기술적 정의
Copy-on-Write는 데이터 수정 시 원본 데이터를 복사한 후 복사본을 수정하는 방식입니다.
원본 데이터는 보존되며, 수정된 데이터는 새로운 위치에 저장됩니다.
구현 메커니즘

첫 번째 이미지(그림 2.66)에서 보이는 CoW 스냅샷 파일 쓰기 작업 과정은 다음과 같습니다:
- 파일 쓰기 요청 발생: 파일 A(0x05)에 대한 수정 요청이 시작됩니다.
- 원본 파일을 읽어 복사: 스냅샷은 먼저 원본 파일 A(0x05)를 읽고, 이 데이터를 메모리로 가져옵니다.
- 복사본 수정 및 새 위치에 저장: 수정된 데이터(0x08)는 스냅샷 출력에 기록됩니다.
- 쓰기 요청 반영: 파일시스템의 파일 A는 A'로 변경되어 새로운 값을 참조합니다.
핵심 기술 기반
CoW는 다음과 같은 리눅스 기술에 기반합니다:
- 페이지 테이블 관리: 리눅스 커널의 메모리 관리 시스템이 가상 메모리 페이지를 물리적 메모리에 매핑할 때 CoW 기법 사용
- mmap()과 fork(): 프로세스 복제 시 메모리 페이지를 실제로 복사하지 않고 참조만 하다가 쓰기 발생 시 복사
- Union Mount: 여러 디렉토리를 하나의 마운트 포인트로 결합하는 기술
3. Redirect-on-Write (RoW) 메커니즘
기술적 정의
Redirect-on-Write는 데이터 수정 시 원본 데이터는 그대로 두고,
변경된 데이터를 새로운 위치에 직접 쓰는 방식입니다. 원본 데이터의 복사 과정이 없습니다.
구현 메커니즘
두 번째 이미지(그림 2.67)에서 보이는 RoW 스냅샷 파일 쓰기 작업 과정은 다음과 같습니다:

- 스냅샷(Freeze) 생성: 파일시스템의 현재 상태를 스냅샷으로 저장합니다(파일 A: 0x05, B: 0x06, C: 0x07).
- 변경사항 기록: 파일 A에 대한 수정이 발생하면, 원본 파일을 읽거나 복사하지 않고 변경된 블록만 새로운 위치에 직접 기록합니다.
- 메타데이터 업데이트: 파일 시스템의 메타데이터가 업데이트되어 수정된 파일 A의 새 위치를 가리킵니다.
핵심 기술 기반
RoW는 다음과 같은 기술에 기반합니다:
- Copy-on-Write 파일시스템: BTRFS, ZFS와 같은 파일시스템에서 구현
- B-트리 데이터 구조: 이러한 파일시스템에서 사용하는 핵심 데이터 구조
- 블록 레벨 스냅샷: 변경된 블록만 새 위치에 기록하는 기술
4. CoW와 RoW 비교
성능 특성
- CoW: 원본 데이터 복사 작업이 필요하므로 쓰기 작업이 더 복잡합니다.
- RoW: 복사 작업이 없어 일반적으로 쓰기 성능이 더 좋습니다.
리소스 사용
- CoW: 수정 작업 시 메모리 사용량이 증가하며, 블록 단위가 아닌 파일 단위로 복사될 수 있어 작은 변경에도 큰 파일 전체가 복사될 수 있습니다.
- RoW: 변경된 블록만 새 위치에 기록하므로 효율적인 공간 사용이 가능합니다.
5. 도커에서의 구현
OverlayFS (CoW 기반)
- 상위 레이어(upperdir)와 하위 레이어(lowerdir)를 통합 뷰(merged)로 제공
- 파일 수정 시 하위 레이어의 파일을 상위 레이어로 복사 후 수정
- Ubuntu 등 많은 리눅스 배포판에서 기본 스토리지 드라이버로 사용

DeviceMapper (CoW 기반)


- 블록 레벨에서 작동하는 스토리지 드라이버
- 씬 프로비저닝 기법을 사용해 필요할 때만 블록 할당
- 커널의 Device Mapper 인프라를 활용한 스냅샷 및 CoW 기능 제공
BTRFS와 ZFS (RoW 기반)

- 파일시스템 자체에 스냅샷 기능 내장
- 변경된 블록만 새 위치에 기록하는 RoW 방식 구현
- 데이터 무결성 검사 및 자가 복구 기능 제공
이러한 기술들은 도커의 효율적인 이미지 관리와 컨테이너 실행을 가능하게 하는 핵심 요소입니다. 특히 계층화된 이미지 시스템을 통해 동일한 기본 이미지를 공유하는 여러 컨테이너가 디스크 공간을 절약할 수 있게 합니다.