Docker에 대해서 알아보자 - 1.Docker의 개념과 생태계

2025. 4. 18. 18:57·프로젝트

💡 도커는 Linux Container를 기반으로 만든 OS 레벨의 가상화를 도와주는 프로그램입니다. Container라는 단위를 이용해서 애플리케이션과 그 실행에 필요한 라이브러리, 설정 파일 등을 하나의 패키지로 묶어, 어떤 환경에서도 동일하게 실행될 수 있도록 보장해 줍니다.

기존의 가상 머신과 달리, 컨테이너는 호스트 OS의 커널을 공유하면서 격리된 공간에서 실행되기 때문에, 리소스 사용이 적고 실행 속도가 빠르며, 배포가 간편하다는 장점이 있습니다. 이러한 특성 덕분에 도커는 개발, 테스트, 운영 환경 간의 차이를 최소화하고, CI/CD, 마이크로서비스, 클라우드 환경에서 매우 널리 사용되고 있습니다.

📌  1.  왜 도커를 써야 할까요?

1️⃣  Environment Disparity 문제 해결

Environment Disparity란 애플리케이션이 개발된 환경과 실제 배포/운영되는 환경이 달라서 생기는 오류를 뜻합니다.

예를 들어서, 
"내 컴퓨터에서는 분명 잘 돌아갔는데 팀원의 컴퓨터에서는 잘 안 돌아간다..!"와 같은 경우가 있을 수 있습니다.

여러 가지 이유로 내 컴퓨터에서 실행하던 코드가 다른 환경에서는 작동하지 않을 수 있습니다.
- 개발자는 Windows에서 개발했는데, 운영 서버는 Linux → 경로/파일 시스템 문제 발생
- 내 로컬에서는 잘 돌아가는데, 다른 팀원이 실행하면 오류 → 라이브러리 버전 차이
- 특정 OS에만 있는 설정 파일 또는 환경 변수 사용
- 라이브러리의 버전 차이와 다른 OS환경

그래서 어떻게 이걸 어떻게 해결하는가?
👉🏻 "내 컴퓨터 환경을 통째로 컨테이너(Container)에 담아버리자!" 

컨테이너는 애플리케이션과 그 실행 환경 전체를 포함한 일종의 패키지이기 때문에, 어디서든 동일한 환경에서 실행할 수 있고, Environment Disparity 문제를 근본적으로 해결해 주기 때문입니다.

2️⃣  가볍고 효율적인 기술

기존에도 Environment Disparity를 해결하는 방법이 있었습니다. 바로 VM입니다.

기존의 VM은 가상 머신을 만들어 주는 Hypervisor(VMvare, VirtualBox... 등등) 위에서 각각의 프로세스마다 자체 운영체제인 Guest OS가 필요했기 때문에 굉장히 무거웠습니다. 운영 체제를 여러 개 돌려야 하니까 리소스 낭비가 엄청 많겠죠..?

하지만, 도커에서는 호스트 OS의 커널을 공유해서 실행되고 컨테이너 안에는 애플리케이션과 필요한 실행 환경(라이브러리, 설정 등)만 담겨있기 때문에 훨씬 가볍고 빠르게 실행될 수 있습니다.

+ VMware에서는 새로운 프로세스를 추가할 때마다 복잡한 설정을 해주어야 했는데 Docker에서는 Container단위만 pull 해 가져와서 실행해 주기만 하면 되기 때문에 매우 편리합니다.

 

이렇게 하게 되면... 하나의 서버에서 독립적인 환경으로 여러 개의 서버를 돌리는 듯한 효과를 가지게 됩니다.

📌 2. 실습환경 세팅 (개인적)

저는 지금부터 작성할 코드들은 AWS EC2의 Ubuntu 환경에서 Docker를 설치하고 진행해 보겠습니다.
공식문서의 내용에 따라서 설치하겠습니다 🔗
1. 도커의 apt repository 세팅
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

 

2. 설치하기

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
3. 설치 확인
sudo docker --version

 

 

저는 위와 같은 방법으로 Docker를 AWS의 EC2 Ubuntu환경에 설치하고 시작했습니다.

(로컬에서 진행하셔도 무방합니다. 로컬에 맞는 방법으로 설치해도 괜찮습니다.)

📌 3. Docker Image란?

먼저 Docker Image라는 것을 이해할 필요가 있습니다.

Application을 포장하고 전송하기 위해 Docker는 Docker Image를 사용합니다.
Docker Image는 애플리케이션 실행에 필요한 독립적인 실행 환경을 포함한 런타임 환경의 템플릿입니다.

 

Docker Image에는 다음과 같은 요소가 포함됩니다:

  • 애플리케이션 소스 코드
  • 필요한 라이브러리
  • 종속성(Dependency) 및 기타 설정 파일들

이 이미지는 불변이며 실행 가능한 단위는 Docker Container입니다. Container는 이미지를 기반으로 생성된 격리된 가상화 환경이며,
이 이미지를 실행 가능한 형태로 만들어주는 portable unit(이동 가능 단위)입니다.

Docker Image는 실행 환경을 정의한 '설정 템플릿'이고, Docker Container는 그 이미지를 실행한 '가상 환경'입니다.

쉽게 말해, 이미지가 설계도면이라면 컨테이너는 그 설계도로 만들어진 가상 컴퓨터라고 보면 됩니다..

 

Docker Image는 여러 개의 읽기 전용(불변) 레이어로 구성되어 있으며, 이 레이어들은 각각 특정 변경 사항이나 설정을 포함합니다. 이처럼 이미지 자체는 변경이 불가능한 구조이기 때문에 안정적인 실행 환경을 제공할 수 있습니다.

 

Docker Container는 이러한 이미지를 기반으로 실행되며, 컨테이너가 생성될 때 이미지 위에 읽기/쓰기 가능한 레이어가 추가됩니다. 이 레이어를 통해 컨테이너 내에서 파일을 수정하거나 새로운 데이터를 생성할 수 있습니다.

📌 4. Docker Image Registry

위에서 설명한 Docker Image를 저장하고 있는 저장소가 Registry입니다. Registry에는 자유롭게 Image를 올릴 수도 있고 pull을 통해서 내려받을 수도 있습니다.

특정 Application에 대한 설정에 대한 부분을 알 필요 없이 Image를 내려받고 실행만 하면 되는 구조입니다!
⭐ 필요한 Image를 찾는다 -> 내려받는다 -> 컨테이너로 실행한다.

 

방법 1: Docker Hub에서 직접 찾기

Dockerhub에서 간단히 원하는 어플리케이션을 검색하고 다운로드하는 code를 확인할 수 있습니다.

 

방법 2: Search 명령어 사용

sudo docker search (검색어)

  • 다음과 같이 Terminal 환경에서 명령어를 통해서 검색이 가능하고 filter를 넣어서 여러 가지 검색 기준을 설정할 수도 있지만...? 
    아무리 봐도 Docker Hub UI에서 찾는 게 더 편해 보이네요..

 

이미지 가져오기 명령어

sudo docker pull (설치 대상)

다운로드한 이미지 확인하기

sudo docker images

이미지 삭제하기

docker rmi <IMAGE_ID or IMAGE_NAME:TAG>

📌 5. Docker Life Cycle

도커 Image와 Container는 어떤 생성 주기를 가지게 될까요?

Registry & Image

  • Push : Registry로 image를 올리는 명령 (권한 필요)
  • Pull : Registry에서 image를 가져오는 명령어

Image & Container

  • Create : Image는 혼자서 실행될 수 없기에 반드시 Container에서 실행해야 함 Container를 띄워주고 이미지 실행 (메모리에 올라감)
  • Commit : 위에서 Image의 레이어에 대해서 설명을 했는데, 컨테이너의 변경 사항을 반영하여 새로운 이미지 생성

Delete

  • rmi(Remove Image) : 이미지 삭제 -> 컨테이너가 내려가지는 않음
  • rm : 컨테이너가 내려감 당연히 메모리에 올라간 부분도 없어짐
  • Stop : 컨테이너의 실행을 멈춤 메모리에 올라간 부분을 없애지만 삭제하지는 않음.

⭐ Run 명령어

  • Run = Pull + Create + Start (이미 Pull이 되어 있을 경우 Pull 생략)
  • Run을 여러 번 호출할 경우 컨테이너가 다수 생기게 됨. 따라서, Create가 필요한 경우에만 사용

🤔 다음 목차에서는 Life Cycle에서 소개한 Docker 명령어에 대해서 조금  더 깊이 알아보겠습니다.

참고 정도로 생각해 주시면 좋을 것 같아요..

📌 6. Docker Life Cycle의 명령어 알아보기 

명령어들에서 TAG가 공통적으로 나오게 되는데 생략될 경우 latest를 사용하게 됩니다.

✅ Push 

# 코드 사용법
docker push [OPTIONS] NAME[:TAG]

# 1. 이미지에 태그 지정
docker tag my-app gamjabat/my-app:1.0

# 2. 이미지 업로드
docker push gamjabat/my-app:1.0

 

OPTIONS

  • -a, --all-tags : 지정한 이미지의 모든 태그를 한 번에 푸시합니다 (모든 버전을 다 push)
  • --disable-content-trust : 이미지 서명을 건너뛰고 푸시합니다. 기본값은 true로 설정되어 있습니다. ​
  • -q, --quiet :푸시 과정의 자세한 출력을 생략하고 간단한 정보만 표시합니다. ​
  • -h, --help : docker push 명령에 대한 도움말을 표시합니다.

이미지 서명 단계는 docker push 시 Notary로 이미지에 디지털 서명을 생성해 저장하고, docker pull 시 그 서명을 확인해 이미지의 무결성과 출처를 검증하는 과정입니다. 

✅ Pull 

# 코드
docker pull [OPTIONS] NAME[:TAG|@DIGEST]

 

OPTIONS

  • -a, --all-tags : 해당 레포지토리의 모든 태그된 이미지를 한꺼번에 내려받습니다.
  • --disable-content-trust : 이미지 서명(Notary) 검증 단계를 건너뜁니다. 기본값은 true.​
  • -q, --quiet :푸시 과정의 자세한 출력을 생략하고 간단한 정보만 표시합니다. ​
  • --platform string : (API ≥1.32) 멀티플랫폼 레지스트리에서 특정 플랫폼(OS/아키텍처)의 이미지만 내려받습니다. 

    ex) ubuntu:20.04는 서로 다른 OS·아키텍처용 이미지(linux/amd64, linux/arm64, windows/amd64 등)를 모아 놓은 메니페스트 리스트(manifest list)를 가르키는데. 원래는 이미 설치되어 있는 OS에 맞는 버전을 다운로드 받지만, 다른 버전을 선택해서 다운로드 가능.

Digest(불변 식별자)로 내려받기

  • 이름+태그 대신 다이제스트를 지정하면 정확히 그 버전을 고정(pinning)할 수 있습니다.

    ex) 최신 버전은 항상 latest가 태그되어 있는데 나중에 최신 버전이 바뀌고 태그가 바뀌어도 불변 식별자인 DIgest를 기반으로 버전을 식별하고 고정할 수 있습니다.

✅  Create (중요)

지정한 이미지를 기반으로 새 컨테이너를 생성만 하고, 실행은 하지 않습니다.

docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
 
create는 도커 컨테이너를 만들어 내는 명령어 이기 때문에 정말 정말 많은 OPTION들이 있었습니다.. 먼저 Docker Container에 대해서 조금 설명하겠습니다.

 

Docker 컨테이너는 하나의 호스트 OS 위에서 일반 프로세스처럼 CPU와 메모리 자원을 할당받아 동시에 여러 개가 실행됩니다.
각 컨테이너는 별도의 제어 그룹(cgroup)으로 묶인 프로세스 집합으로 취급되며, 호스트 OS가 해당 cgroup에 설정된 CPU·메모리 할당량에 따라 자원을 관리합니다.

도커의 CPU 제약 설정

  • 컨테이너는 호스트 CPU 사이클을 무제한으로 사용할 수 있습니다.
  • 여러 컨테이너가 동시에 CPU 자원을 요청할 때면(경쟁) 제약이 작동하며 리눅스 CFS(Completely Fair Scheduler) 스케줄러가 균등하게 나눠 줍니다.

도커의 메모리 관리

  • CPU처럼 컨테이너에 메모리 제약이 전혀 없으면, 호스트 커널이 허용하는 한 최대한 많은 메모리를 사용합니다.
  • 주의 사항 OOM 위험:
    • 호스트에서 메모리가 부족해지면 커널이 OOM(Out Of Memory) 상황을 감지하고 프로세스를 강제 종료(“OOM Killer”)하여 메모리를 회수합니다.
    • 다만, 하나의 컨테이너가 죽는 것은 상관없지만..! 만약 Docker 데몬이 죽게되면.. 하나의 컨테이너가 일으킨 OOM에 의해서 다른 컨테이너와 Docker 프로세스 자체가 죽을 수도 있습니다.

      따라서, Docker에서는 Docker 데몬 프로세스의 OOM 우선순위를 높여놓고 컨테이너가 먼저 죽도록 설정이 되어 있습니다.
      --oom-score-adj는 -1000(절대 보호)에서 +1000(절대 희생) 사이의 값을 지정해, 커널이 OOM(메모리 부족) 시 어떤 프로세스를 먼저 죽일지 우선순위를 조정하는 옵션으로 

      도커 데몬(dockerd) = 500
      컨테이너 프로세스 = 0 

      정도로 설정이 되어 있습니다. 
      --oom-score-adj 설정을 따로 해줄 수 있는데, 마음대로 조정하면 위험할 수도 있습니다.
  • 도커의 Swap 메모리 사용법
    • --memory + --memory-swap를 통해서 총 한도를 설정해 주어야 합니다. 설정하지 않는다면 커널의 최대한 많은 메모리와 스왑을 사용합니다.

      ex) --memory=300m --memory-swap=1g→ 300MiB RAM + (1GiB−300MiB)=724MiB 스왑 사용 허용을 뜻 합니다.
    • --memory를 설정하고 --memory-swap을 설정하지 않는다면, 설정한 메모리 만큼 swap을 사용합니다.
    • --memory-swap == --memory를 설정하면 스왑을 금지합니다.
    • --memory-swap = -1를 설정하면 호스트 한도까지 무제한 스왑이 가능합니다.
💡 OPTION이 너무 많은 관계로 어떤 기능들을 설정할 수 있는지 정도만 정리해 보겠습니다. 

구체적으로 확인하고 싶다면, 링크를 통해서 확인해 주세요  🔗

 

1. 네트워크 설정

이렇게 네트워크 드라이버 선택부터 IP·DNS·서비스 이름, 포트 매핑, 호스트 파일 조작까지 컨테이너가 “어떤 네트워크에서, 어떻게, 어떤 이름으로, 어떤 포트로” 통신할지 전반을 설정할 수 있습니다. 

 

⚠️ 중요한 점은 Container 끼리 network 만들어서 연결해 줄 수 있다는 점입니다.
예를 들어서 Redis를 하나의 컨테이너로 띄우고 Spring 애플리케이션을 다른 Container로 띄우게 된다면 Redis를 이용해서 캐싱을 하기 위해서는 컨테이너끼리 소통이 가능해야 합니다.

 

2. 자원 관리

위에서 설명했던 CPU 스케줄링, 메모리 관리, 그리고 블록 I/O에 대한 설정을 할 수 있습니다.

 

3. 볼륨/마운트 설정

컨테이너는 호스트 경로를 직접 마운트 하거나, 컨테이너 간에 공유되는 Docker 볼륨을 사용할 수 있습니다.

 

4. 보안 및 격리

컨테이너의 시스템 권한, 네임스페이스 격리 범위, OOM 처리 방식을 세밀하게 설정해 보안과 안정성이 보장되는 환경을 구축할 수 있습니다. OOM과 관련한 세팅을 할 수 있는 만큼 위에서 설명했던 주의 사항을 숙지해야 합니다.

 

5. 실행 모드 유틸리티

터미널 입출력 제어, 환경 변수 및 작업 디렉터리 설정, 컨테이너 종료 시 자동 정리, 그리고 컨테이너 식별·도움말 확인 기능을 한 번에 제공하는 옵션들입니다.

 

⚠️ Container와 호스트는 다른 환경 변수를 사용하기 때문에 환경 변수를 요구하는 어플리케이션을 Container에서 실행하게 된다면 따로 전달을 해주어야 합니다..

 

6. 로킹-모니터링 설정

로그 드라이버 설정과 헬스체크 명령·간격·재시도·타임아웃 등의 세부 조건을 지정하거나 비활성화할 수 있는 옵션들입니다.

✅  Commit

실행 중인 컨테이너의 파일 변경사항이나 설정을 새로운 이미지로 저장합니다.

docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

 

OPTIONS

  • -a, --author : 이미지 메타데이터에 기록할 작성자 정보
  • -c, --change : 생성된 이미지에 적용할 Dockerfile 지시문 (CMD, ENV 등). 여러 번 지정 가능​
  • -m, --message : 커밋 메시지​
  • -p, --pause : 커밋 중 컨테이너를 일시 정지할지 여부 (false로 설정하면 정지하지 않음 default는 true). 

✅  Run

docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]

 

Run = Pull(필요시) + Create + Start 인 만큼 모든 과정의 Option을 설정해 줄 수 있습니다.

📌 7.  도커 아키텍처 & 도커 데몬(Daemon)

도커는 다음과 같은 아키텍처를 가지고 있는데요 이제는 어떤 구조로 작동하는지 파악할 수 있습니다.
클라이언트의 요청에 따라서 이미지와 컨테이너를 관리하고 Registry를 통해서 이미지를 업로드하기도 다운로드하기도 합니다.

그런데 이 모든 과정이 원활하게 작동할 수 있도록 도와주는 것을 Docker Daemon(도커 데몬)이라고 부릅니다.

Docker는 다음과 같이 호스트의 OS위에 Docker Engine이 있고 그 위에서 Container들이 실행되게 됩니다. Docker Engine의 구성요소는 다음과 같습니다.  

  • docker CLI : 도커 명령어를 보내기 위한 전용 인터 페이스 (like 터미널)
  • docker daemon : Docker 엔진의 “백그라운드 서비스” 그 자체
  • Docker API : 도커 명령어를 수행하는 RESTful 인터페이스.

docker daemon(도커 데몬)은 Docker 엔진의 핵심적인 서비스 그 자체인 것입니다.

컨테이너의 생성·실행·중지·삭제 및 이미지 빌드·풀·푸시, 가상 네트워크·볼륨 스토리지·보안 격리 기능등 사실상 도커 엔진이 하는 모든 역할을 실행하는 서비스가 docker daemon입니다.

 

그리고 도커 데몬의 실행 파일(바이너리)를 dockerd라고 부릅니다.

 

도커 데몬에서는 소켓과 관련된 설정부터 보안, 로그, 스토리지, 네트워크, 그리고 런타임 등등..
다양한 설정을 할 수 있고 3가지 방법으로 설정이 가능합니다.

  1. CLI 플래그 : dockerd --… 를 터미널에 입력해서 설정.
  2. 설정 파일 수정 : /etc/docker/daemon.json에 설정을 입력
  3. 환경 변수 설정 :(HTTP_PROXY, DOCKER_DRIVER 등)

이 순서로 우선순위가 적용되어, 위쪽에 가까울수록 더 높은 우선권을 가집니다.

📌 8. 이외에도 유용할 수도 있는 기능들

공식 문서를 읽어보면서, 실제 프로젝트에서 사용해 봤던 기능들과 유용할 것만 같은 기능들만 정리해봤습니다.

✅  컨테이너 터미널 열기

docker exec

# 1) 백그라운드(Detached)로 명령 실행하기
# 실행 중인 컨테이너 mycontainer 내부에 /tmp/hello.txt 파일을 생성하고 즉시 프롬프트 복귀
docker exec -d mycontainer touch /tmp/hello.txt

# 2) 인터랙티브(Interactive)로 셸 진입하기
# 컨테이너 mycontainer 내부에 bash 셸을 띄워, 키보드 입력과 화면 출력을 실시간으로 주고받음
docker exec -it mycontainer bash
  • 컨테이너에 터미널을 백그라운드 또는 인터렉티브 모드로 실행 
docker exec -e VAR_A=1 -e VAR_B=2 mycontainer env

✅ 컨테이너 상태 및 로그 확인하기

 docker ps

$ docker ps
CONTAINER ID   IMAGE           COMMAND                  CREATED        STATUS        PORTS     NAMES
d5e49d9ab3f4   ubuntu:20.04    "/bin/bash"              2 hours ago    Up 2 hours    0.0.0.0:80->80/tcp   my-container
f2a123dbb9a7   nginx:latest    "/docker-entrypoint.…"   3 hours ago    Up 3 hours    0.0.0.0:8080->80/tcp  nginx-container
  • docker ps를 통해서 실행 중인 Container에 대한 정보를 확인할 수 있습니다.

docker ps -a

$ docker ps -a
CONTAINER ID   IMAGE           COMMAND                  CREATED        STATUS                    PORTS     NAMES
d5e49d9ab3f4   ubuntu:20.04    "/bin/bash"              2 hours ago    Up 2 hours                0.0.0.0:80->80/tcp   my-container
f2a123dbb9a7   nginx:latest    "/docker-entrypoint.…"   3 hours ago    Exited (0) 5 minutes ago   0.0.0.0:8080->80/tcp  nginx-container
f342b1b3c3c7   alpine:latest   "echo Hello Docker"      5 hours ago    Exited (0) 2 hours ago                 hello-container
  • docker ps - a를 통해서 실행이 종료된 Container에 대한 정보도 확인할 수 있습니다.

docker logs

$ docker logs f2a123dbb9a7  //Container-id이용
$ docker logs nginx-container //Container name이용

$ docker logs --tail (줄 수) (컨테이너 이름)
$ docker logs --tail 10 nginx-container
  • 프로젝트를 하면서 실제로 많이 사용했던 부분입니다. 

    배포 과정에서 오류가 있는 경우? Docker Container가 계속 죽게 되는데 docker ps -a -> docker logs를 통해서 오류의 원인을 파악할 수 있습니다.

✅ 컨테이너 상세 조회

docker inspect

# 결과 예시
[
  {
    "Id": "f1a2b3c4d5e6",
    "Name": "/mycontainer",
    "Image": "sha256:abcdef123456…",
    "Created": "2025-04-21T10:15:30.123456789Z",
    "Path": "/bin/sh",
    "Args": ["-c", "npm start"],
    "State": {
      "Status": "running",
      "Running": true,
      "StartedAt": "2025-04-21T10:15:31.987654321Z",
      …
    },
    "Config": {
      "Env": ["NODE_ENV=production","PORT=3000"],
      "Cmd": ["npm","start"],
      …
    },
    "NetworkSettings": {
      "IPAddress": "172.18.0.2",
      "Ports": {
        "3000/tcp": [{"HostIp":"0.0.0.0","HostPort":"3000"}]
      }
    },
    …
  }
]

 

✅ 정지 상태 Container 모두 삭제하기

docker prune

# 10분 전에 생성된 정지 컨테이너만 필터해 삭제
docker container prune --force --filter "until=10m"

 

  • --force (-f) : 확인 없이 바로 삭제 실행
  • --filter "until=<조건>" : 생성 시각, 레이블로 필터링

✅ 컨테이너 통계 확인 후 튜닝

docker stats

docker stats

CONTAINER ID        NAME                                    CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
b95a83497c91        awesome_brattain                        0.28%               5.629MiB / 1.952GiB   0.28%               916B / 0B           147kB / 0B          9
67b2525d8ad1        foobar                                  0.00%               1.727MiB / 1.952GiB   0.09%               2.48kB / 0B         4.11MB / 0B         2
e5c383697914        test-1951.1.kay7x1lh1twk9c0oig50sd5tr   0.00%               196KiB / 1.952GiB     0.01%               71.2kB / 0B         770kB / 0B          1
4bda148efbc0        random.1.vnc8on831idyr42slu578u3cr      0.00%               1.672MiB / 1.952GiB   0.08%               110kB / 0B          578kB / 0B          2
  • 도커는 CPU와 메모리 등을 컨테이너마다 다르게 분배하고 설정할 수 있는데 효율적으로 최적화하기에 앞서서 좋은 시각화 기능 같습니다.

docker update

docker update --cpu-shares 512 abebf7571666
  • docker update는 cpu와 memory에 관련한 간단한 설정들을 container를 중지시키지 않고 바꿀 수 있는 명령어입니다.
    지원하지 않는 설정(네트워크 모드, 볼륨, 엔트리포인트 변경 등)은 docker update로 바꿀 수 없고, 컨테이너를 새로 run 해야 합니다.

    만약, 컨테이너에서 중요한 서비스가 실행되고 있어서 내릴 수 없고 CPU나 Memory 자원을 보충해 주어야 하는 상황이 발생한다면 사용할 수도 있다고 생각했습니다.

✅ 도커 이미지 관리하기

docker images

docker images

REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
<none>                    <none>              77af4d6b9913        19 hours ago        1.089 GB
committ                   latest              b6fa739cedf5        19 hours ago        1.089 GB
<none>                    <none>              78a85c484f71        19 hours ago        1.089 GB
docker                    latest              30557a29d5ab        20 hours ago        1.089 GB
<none>                    <none>              5ed6274db6ce        24 hours ago        1.089 GB
postgres                  9                   746b819f315e        4 days ago          213.4 MB
postgres                  9.3                 746b819f315e        4 days ago          213.4 MB
postgres                  9.3.5               746b819f315e        4 days ago          213.4 MB
postgres                  latest              746b819f315e        4 days ago          213.4 MB
  • 존재하는 도커 이미지에 관한 정보를 볼 수 있습니다. 쌓이면 용량이 꽤 크기 때문에 사용하지 않는 것들은 지워주도록 합시다.

docker image history

docker image history [OPTIONS] IMAGE

IMAGE          CREATED         CREATED BY                                      SIZE
7e4a0e0d8c0d   2 days ago      /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B
<missing>      2 days ago      /bin/sh -c set -x     && apt-get update     …   63.5MB
<missing>      3 weeks ago     /bin/sh -c #(nop)  LABEL maintainer=NGINX …   0B
<missing>      3 weeks ago     /bin/sh -c addgroup    --system --gid 101 …   1.24MB
  • 이미지 레이어의 정보를 확인할 수 있습니다.

✅ 컨테이너 간 통신 설정 및 공유 스토리지

docker volume

# 1. 공유볼륨 생성
docker volume create shared_data
# → 생성된 볼륨 이름: shared_data

# 2. 컨테이너 A(writer) 에서 볼륨에 파일 쓰기
docker run --rm \
  --name writer \
  -v shared_data:/data \
  busybox \
  sh -c "echo 'Hello from A!' > /data/message.txt"

# 3. 컨테이너 B(reader) 에서 같은 볼륨을 마운트하고 메시지 읽기
docker run --rm \
  --name reader \
  -v shared_data:/data \
  busybox \
  sh -c "cat /data/message.txt"
# 출력: Hello from A!
  • docker volume이라는 컨테이들 사이에 공유해서 사용하는 스토리지를 만들고 경로를 -v 명령어로 마운트 해서 컨테이너 간 정보를 공유할 수 있습니다.

docker network

# 네트워크 생성
docker network create app-net

# Redis 컨테이너 실행
docker run -d \
  --name redis \
  --network app-net \
  redis:6-alpine

# Spring 컨테이너 실행
docker run -d \
  --name spring-app \
  --network app-net \
  -e SPRING_REDIS_HOST=redis \
  -e SPRING_REDIS_PORT=6379 \
  my-spring-app:latest
  • Create 부분에서도 설명했듯이.. 컨테이너간 네트워크 설정을 해주지 않으면 서로 소통이 되지 않습니다. 하나의 Container에서 Spring 애플리케이션을 돌리고 Redis 컨테이너를 띄워서 캐싱을 하고자 한다면 두 개의 컨테이너가 동일 네트워크에 존재해야 합니다.

✅  ETC

docker context

Docker Context는 로컬이든 원격이든, 심지어 클라우드상의 Docker 엔진이든, 한 번의 설정으로 터미널에서 docker 명령을 그대로 보내 실행할 수 있게 해 주는 프로파일 기능입니다.

 

예를 들어서, 회사에 존재하는 원격 데몬에 명령어를 보내기 위해서는 회사 서버에 접속해서 docker 명령어를 작성할 수도 있지만..?

docker context로 회사 데몬 정보를 저장해 두면 간단히 프로필 전환만으로 로컬에서 회사 데몬으로 명령을 보낼 수 있습니다.

 

AWS 서버 터미널을 로컬 인텔리제에 ssh 인증으로 연결해 두는 것과도 비슷하다고 볼 수 있을 것 같습니다.

📌 9.  도커를 이용한 배포 프로세스

도커의 기본적인 CLI reference와 개념들에 대해서 거의 모두 정리한 것 같습니다(Kubernetes와 Swarm 같은 오케스트레이션 제외). 

마지막으로 도커를 배포에 활용하기 위한 방법에 대해서 알아보겠습니다.

 

일반적으로, 다음과 같은 과정을 통해서 배포 프로세스를 진행합니다.

 

1. Dockerfile에 명시된 내용들을 바탕으로 docker build명령어를 실행 Image를 빌드합니다
2. Image를 Docker Repository로 push
3. 배포 환경에서 Docker Image를 pull 해 가져온다
4. docker-compose.yml에 정의된 서비스들을 docker compose up명령어를 통해서 배포 환경의 백그라운드에 실행

Best Practice에서는 다음과 같이 배포 프로세스를 구성할 것을 권장합니다.

DockerFile
은 “이미지를 어떻게 조립할 것인가”에 대한 내용(RUN, COPY, ENV, ARG, LABEL, 멀티스테이지 스테이지 이름 등)을 담고 있습니다. 

docker build라는 명령어는 명령어만 보면 이미지를 만드는 것에 대한 부분을 설정할 것 같지만, 조립을 어떻게 최적화하거나 어디로 내보낼 것인지”에 대한 고급 옵션(멀티플랫폼, 캐시, 시크릿, SSH, 출력 형식, 리소스 제한 등)을 설정하는 경우가 일반적입니다.

docker-compose.yml에서는 ports, volumes, environment, deploy-resources 등 컨테이너 런타임과 관련된 설정을 담고 있습니다.

 

이어지는 게시물들에서는 각각에 대해서 알아보고 어떻게 사용하면 되는지 알아보겠습니다.

 

Reference :

벨로그 - 도커 : Docker와 VM의 차이 by David Kim 🔗

티스토리 - [Docker] 도커 사용법 정리 - 설치, 컨테이너, 볼륨, 이미지 by 끈기JK 🔗

노션 - 왕초보도 따라 하는 도커 기초 강의 🔗

phonexNAP -Docker Image vs. Container: The Major 🔗

도커 공식 문서 🔗

티스토리 - [Docker] 11.도커 데몬(Daemon) by 별준 🔗

'프로젝트' 카테고리의 다른 글

Docker에 대해서 알아보자 - 3. docker build & docker compose  (0) 2025.04.26
Docker에 대해서 알아보자 - 2.Dockerfile  (1) 2025.04.26
배포의 모든 것 - 4. 도메인 연결과 HTTPS 적용하기  (0) 2025.04.03
배포의 모든 것 - 3. Github Action을 통한 CI/CD  (0) 2025.03.18
배포의 모든 것 - 2. RDS와 Session Manager  (0) 2025.02.25
'프로젝트' 카테고리의 다른 글
  • Docker에 대해서 알아보자 - 3. docker build & docker compose
  • Docker에 대해서 알아보자 - 2.Dockerfile
  • 배포의 모든 것 - 4. 도메인 연결과 HTTPS 적용하기
  • 배포의 모든 것 - 3. Github Action을 통한 CI/CD
나는 정말 개발이 하고 싶었다
나는 정말 개발이 하고 싶었다
개발 혼자 공부하기
  • 나는 정말 개발이 하고 싶었다
    감자밭
    나는 정말 개발이 하고 싶었다
  • 전체
    오늘
    어제
    • 분류 전체보기 (32)
      • ETC (3)
      • 알고리즘 (0)
      • Java (0)
      • DB (2)
      • Spring (0)
      • 프로젝트 (18)
      • Server (3)
      • CS (0)
        • 운영체제 (0)
      • Infra (4)
        • IAC (1)
        • AWS (3)
  • 블로그 메뉴

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

  • hELLO· Designed By정상우.v4.10.3
나는 정말 개발이 하고 싶었다
Docker에 대해서 알아보자 - 1.Docker의 개념과 생태계
상단으로

티스토리툴바