김가은-2
[따베도] 도커 시리즈 - 이론
3-1. 도커 컨테이너 살펴보기 - 이론편
4-1. 도커 컨테이너 만들기 - 이론편
5-1. 컨테이너 보관창고 - 이론편
6-1. Docker 컨테이너 사용하기 - 이론편
7-1. Docker 컨테이너 리소스 관리 - 이론편
8-1. Docker Container Storage - 이론편
9-1. 컨테이너간 통신(네트워크) - 이론편
10-1. 빌드에서 운영까지 (using Docker Compose) - 이론편
컨테이너와 컨테이너 이미지
컨테이너
하나의 애플리케이션 실행 단위로, 독립된 환경에서 실행되는 프로세스
서로 완전히 분리된 공간에서 실행되므로, 다른 컨테이너에 영향을 주지 않음
각 컨테이너는 CPU, 메모리, 네트워크, 디스크 리소스를 가상으로 독립적으로 할당받음
개발자는 특정 컨테이너만 수정해서 기능을 업데이트할 수 있음 (모듈성 ↑)
컨테이너 이미지
컨테이너 실행을 위한 정적인 파일 조합
디스크에는 읽기 전용 파일 형태로 저장됨
여러개의 Layer로 구성되어 하나의 어플리케이션이 실행될 수 있도록 모아져있
명령어
docker pull
,docker run
등을 통해 Docker Hub 같은 저장소에서 가져올 수 있음
컨테이너 이미지 구조 상세
컨테이너 VS 컨테이너 이미지
구분 | 컨테이너 이미지 | 컨테이너 |
---|---|---|
정의 | 실행을 위한 설계도 | 실제 실행 중인 인스턴스 |
형태 | 파일 (Read-Only) | 프로세스 (Read/Write) |
저장 위치 | 하드디스크 | 메모리 |
명령어 |
|
|
컨테이너와 컨테이너 이미지 동작 방식
Docker Hub 등에서 이미지 다운로드 (
docker pull
)컨테이너 생성 및 실행 (
docker run
)이미지 기반으로 컨테이너가 메모리에서 프로세스로 실행됨
호스트 입장에서는 컨테이너가 하나의 격리된 프로세스로 보임
용어 정리
컨테이너 이미지 : 디스크에 저장된 정적인 구성 정보 (읽기 전용)
컨테이너 : 이미지를 기반으로 실행된 동적 프로세스 (읽기/쓰기 가능)
Docker Daemon : 이미지를 관리하고, 컨테이너를 실행하는 핵심 엔진
Docker Client : 사용자가 명령을 입력하는 인터페이스
Docker Host : 위 모든 것이 동작하는 머신
Docker Hub : 이미지 저장소
컨테이너 만들기
무엇으로 컨테이너를 만드는가
컨테이너 하나 = 하나의 애플리케이션
애플리케이션이 실행되기 위해선 다음 구성요소 필요:
운영 환경 (런타임): 예) Node.js, Python, PHP 등
애플리케이션 소스 코드:
app.js
,main.py
등실행 명령어: 컨테이너 시작 시 실행될 명령어
예시:
쇼핑몰 전체 플랫폼 → 다양한 기능별 컨테이너로 구성 (쇼핑카트, 주문 서비스, 상품관리 등)
각 컨테이너는 적절한 언어/프레임워크를 기반으로 구성
이 방식은 마이크로서비스 아키텍처(MSA) 로 확장 가능
컨테이너는 어떻게 만드는가 → Dockerfile
Dockerfile : 컨테이너 이미지를 생성하기 위한 설정 명령어 모음파일일
자주 쓰는 명령어:
FROM
: 기반 이미지 (예:node:14
)COPY
: 소스코드 복사CMD
: 컨테이너 실행 시 실행할 명령어
지시어 | 의미 |
---|---|
| 베이스 이미지 지정 (운영 환경) |
| 소스코드 또는 파일 복사 |
| 컨테이너 실행 시 실행될 명령 |
|
|
컨테이너를 배포하기
컨테이너 이미지를 다른 사람들과 공유하려면 레지스트리(Hub) 에 등록
대표적인 레지스트리:
퍼블릭: Docker Hub (http://hub.docker.com )
프라이빗: 사내 자체 저장소(ex: Harbor)
배포 절차 순서
docker login
(허브 로그인)docker build
(이미지 생성)docker push
(허브에 업로드)
컨테이너 보관함
Container Registry
컨테이너 이미지를 저장하는 저장소
컨테이너 이미지들을 모아두고 필요할 때 가져다 씀 (
pull
), 새로 올리기도 함 (push
)Docker Hub (공개/퍼블릭) : hub.docker.com에서 제공하는 공식 저장소
Private Registry (사내/프라이빗) : 보안, 내부 배포 목적으로 회사 내부에서 직접 운영하는 저장소. Docker Hub와는 달리 외부에 노출되지 않음.
Docker Hub (공개/퍼블릭)
Docker Hub Container Image Library | App Containerization 에서 이미지 직접 검색 또는 CMD 에서 검색 가능
커맨드라인에서도 검색 가능:
docker search <이미지명>
Private Registry (사내/프라이빗)
Docker Hub에서 registry
컨테이너를 사용
명령 예시:
docker run -d -p 5000:5000 --restart=always --name registry registry:2
이미지를 push할 때는 이름 앞에 Registry 주소 (
IP:Port
)를 붙임
docker tag myapp localhost:5000/myapp
docker push localhost:5000/myapp
컨테이너 실행 라이프사이클
컨테이너 이미지 사용
검색 : docker search <이미지명>
다운로드 : docker pull <이미지명[:태그]>
목록 확인 : docker images
상세 정보 : docker inspect <이미지명>
삭제 : docker rmi <이미지명>
컨테이서 실행하기 (이미지 → 싫행 중인 컨테이너 만들기)
이미지는 Disk에 저장되고, 컨테이너로 만든 다음 실행을 해줘야 메모리 위에 올라감
컨테이너 생성 : docker create --name <이름> <이미지>
컨테이너 실행 : docker start <컨테이너 이름>
이미지 Pull+Create+Start 한번에 실행 : docker run --name <이름> <이미지>
컨테이너 종료 : docker stop <이름>
컨테이너 삭제 (이미지는 유지) : docker rm <이름>
동작중인 컨테이너 상태 확인
목록 조회 : docker ps (-a 로 종료된 컨테이너까지 포함)
상세 확인 : docker inspect <컨테이너 이름> → inspect 명령어는 이미지도 가능
로그 보기 : docker logs <컨테이너 이름>
프로세스 확인 : docker top <컨테이너 이름> → 컨테이너 내 실행중인 프로세스 조회
명령 원격 실행 : docker exec -it <컨테이너> bash (접속)
중지/재시작 : docker stop, docker start, docker restart
Docker 컨테이너 리소스 관리
리소스 제한의 필요성
컨테이너는 기본적으로 호스트 리소스(CPU, 메모리, 디스크)를 제한 없이 모두 사용 가능함
여러 컨테이너가 동시에 실행될 경우 리소스 쟁탈이 발생함 → 일부 컨테이너가 과도하게 리소스 사용 가능
따라서 컨테이너 실행 시 적절한 리소스 제한(쿼터) 설정이 요구됨
메모리 리소스 제한
예) docker run -m 512m nginx
옵션 | 설명 |
---|---|
| 최대 사용 메모리 크기 (예: |
| 최소 보장 메모리 |
| 메모리 + 스왑 공간의 총합 제한 (즉, 스왑 =
|
| 메모리 부족 시 강제 종료 방지 (OOM Kill 방지)
|
CPU 리소스 제한
예) docker run --cpus=1.5 nginx
옵션 | 설명 |
---|---|
| 사용할 CPU 비율 (예: |
| 특정 CPU 코어만 지정 (예: |
| 상대적 CPU 점유 비율 (기본: 1024) |
Disk I/O 리소스 제한
옵션 | 설명 |
---|---|
| I/O 우선순위 (10~1000, 기본: 500) |
| 초당 읽기 속도 제한 (예: |
| 초당 쓰기 속도 제한 |
| 초당 읽기 IOPS 제한 |
| 초당 쓰기 IOPS 제한 |
컨테이너 리소스 모니터링 도구
명령어 | 설명 |
---|---|
| 실시간으로 컨테이너 CPU, 메모리, I/O 사용량 확인 |
| 컨테이너 관련 이벤트 실시간 모니터링 (시작, 중지 등) |
| 구글에서 만든 컨테이너 리소스 모니터링 웹 툴 (별도 설치) |
Docker Container Storage
Container Volume
컨테이너 이미지 → 읽기 전용(Read-only)
컨테이너가 실행이 되어야만 읽고 쓰기 가능한 레이어(Read/Write Layer) 가 추가됨.
이 데이터는 컨테이너가 삭제되면 함께 사라짐 → 영구 저장 불가함
데이터를 영구족으로 보존하기
호스트 디스크에 별도 저장공간을 마련해서 마운트(연결) 해야 함.
→ 컨테이너 안에서 생성된 데이터가 호스트 디스크에 저장되기 때문에 컨테이너가 삭제돼도 데이터는 보존
예) docker run -v /host/db:/var/lib/mysql ...
-v
옵션 사용:
docker run -v [호스트 디렉토리]:[컨테이너 디렉토리] ...
보안상 읽기 전용 마운트(Read-only) 도 가능
예) docker run -v /host/web:/usr/share/nginx/html:ro ...
볼륨 종류
바인드 마운트: 호스트 디렉토리 지정
익명 볼륨: 호스트 경로 생략 → Docker가 임시 위치 자동 생성
네임드 볼륨: Docker가 관리하는 이름 있는 저장소 사용 (
docker volume create
등)
컨테이너 간 통신
컨테이너 네트워크 구조
컨테이너는 기본적으로
docker0
브리지 네트워크(172.17.0.1)를 통해 통신함. → 게이트웨이 역할컨테이너에 내부 IP (172.17.0.x)가 자동 할당됨
브리지 네트워크는 NAT와 포트포워딩을 통해 외부와 통신 가능.
컨테이너 포트를 외부로 노출
웹 기반의 서비스의 경우 외부에서 컨테이너의 80 포트로 연결되어야 함 이럴 때 어떻게 통신이 이루어지는가
docker run -p [호스트포트]:[컨테이너포트]
docker run -p [컨테이너포트] --> 호스트포트는 랜덤매칭됨
docker run -P --> 컨테이너에서 EXPOSE된 포트가 자동 매핑됨.
예 ) docker run --name web -d -p 80:80 nginx:1.14
-p 8080:80
→ 호스트 8080 요청이 컨테이너의 80번 포트로 전달됨.동일한 호스트 포트를 여러 컨테이너에 할당할 수는 없음
포트포워딩 결과는 iptables 에서 확인 가능 (iptables -t nat -L -n -v)
컨테이너에 Static IP 를 할당하는 방법
User Defined Bridge Network를 생성해 원하는 대역의 네트워크와 Static IP 지정 가능
단, User Defined Bridge Network를 생성하지 않으면 지정 불가함
$docker network create --driver bridge \
--subnet 192.168.100.0/24 \
--gateway 192.168.100.254 \
mynet
이 네트워크를 사용할 경우, 컨테이너에 스태틱 IP도 지정 가능.
$docker run -d --name web -p 80:80 \
nginx1.14
$docker run -d --name appjs \
--net mynet --ip 192.168.100.100 \
-p 8080:8080 \
smlinux/appjs
컨테이너끼리 통신
같은 브리지 네트워크에 속하면 컨테이너 이름으로 통신 가능.
또는
--link
옵션을 통해 컨테이너 간 통신 설정 가능 (구버전 방식).예: WordPress 컨테이너에서 MySQL 컨테이너로 연결
$docker run -d --name mysql \ -v /dbdata:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=wordpress \ -e MYSQL_PASSWORD=wordpress mysql:5.7 $docker run -d --name wordpress --link mysql:mysql \ -e WORDPRESS_DB_PASSWORD=wordpress -p 80:80 wordpress:4
WordPress는 MySQL에 링크된
mysql
호스트명으로 접근 가능하게 됨
Docker Compose
Docker Compose란
컨테이너를 실행할 때 지정하는 옵션 등을 YAML 파일로 만들어서 Docker Compose가 실행하게 됨
여러 개의 컨테이너를 일괄적으로 정의하고 실행할 수 있는 도구
docker run
명령을 대신해 여러 설정을 YAML 파일에 정의YAML 파일을 기준으로 이미지, 포트, 볼륨, 링크, 환경변수 등을 지정 가능
Compose 명령어들:
docker-compose up
: 전체 컨테이너 실행docker-compose ps
: 실행 상태 확인docker-compose stop
/down
: 컨테이너 중지/삭제docker-compose logs
: 로그 보기docker-compose scale
: 서비스 인스턴스 개수 조절
YAML 작성하기
https://docs.docker.com/reference/samples/ 여기서 예제 YAML 파일이 제공됨
도커 컴포즈로 빌드부터 운영까지
1단계 : 서비스 디렉토리 생성
$ mkdir composetest
$ cd composetest
2단계 : 빌드를 위한 Dockerfile 생성
$ cat > Dockerfile
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
3단계 : docker-compose.yml 생성
$ cat > docker-compose.yml
version: "3"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
4단계 : docker-compose 명령어 실행
$ docker-compose up -d