[Docker] Docker의 모든 것

2025. 9. 7. 13:11·DevOps

1. 기본 개념 이해

백엔드 개발에서 발생하는 문제

백엔드 개발자가 만든 프로그램을 다른 사람(팀원이나 서버)에 옮겨서 실행하려고 할 때 '왜 내 컴퓨터에서는 잘 되는데 서버에서는 오류가 나지?' , '버전이 달라서 쿼리가 안돌아간다고?' 와 같이 실행이 안되는 경우가 정말 많다. 나도 처음 UMC 프로젝트를 하는데 Docker를 사용하지 않아, 각자 환경이 달라서 '제 로컬에서는 되는데요...?' 라고 했던 경험이 있다. 

→ Docker는 이 문제를 해결하는 도구이다. 

Docker의 핵심 아이디어 

Docker는 프로그램을 실행하기 위해 필요한 모든 것(코드, 라이브러리, 설정, 운영체제 일부)을 하나의 상자 안에 담는다. 그리고, 그 상자를 우리는 `이미지(Image)`라고 한다. 이미지를 실행하면 `컨테이너(Container)`가 된다. 

이미지 = 프로그램 실행을 위한 설계도 
컨테이너 = 이미지를 켜서 돌아가는 실제 프로그램 

 

VM(가상머신)과 다른 점 ? 

사람들이 종종 Docker를 "가상머신과 비슷하다" 라고 생각하는데, 사실 많이 다르다. 

  • 가상머신(VM)은 운영체제(OS) 전체를 가상으로 올려 무겁고, 느리고, 리소스를 많이 사용하게 된다. 
  • 반면 Docker는 프로그램 실행에 꼭 필요한 부분만 격리시켜 가볍고, 빠르고, 리소스를 적게 사용한다. 

왜 Docker가 필요할까 ? 

환경을 통일할 수 있다. 개발자, 서버, 노트북 어디에서 실행해도 똑같이 동작하도록 할 수 있다. 또한, 배포에 편리하다. `docker run` 한 줄로 서버에 편리하게 배포를 할 수 있다. 또한 MySQL이나 Redis와 같은 프로그램을 매번 설치할 필요 없이 Docker Hub에서 이미지를 받아 바로 실행할 수 있다.


2. Docker의 주요 구성 요소 

1) Docker Engine 

Docker의 심장 같은 역할을 하며 개발자가 `docker run`, `docker build` 와 같은 명령어를 입력하면, 실제로 컨테이너를 만들고 실행하는 엔진이다. 운영체제 안에서 돌아가는 하나의 프로그램이고, 이미지 → 컨테이너 실행 과정을 담당한다. 

 

2) Docker Image 

이미지는 프로그램 실행을 위한 설계도 또는 완성된 요리 레시피라고 생각하면 된다. 안에는 코드, 라이브러리, 환경 설정, 실행 방법까지 다 들어있으며 이미지를 실행하면 컨테이너가 된다. 

 

3) Docker Containers 

컨테이너는 이미지를 실제로 켜서 돌아가는 실행 중인 프로그램이다. 컨테이너는 격리된 환경에서 실행되기 때문에 다른 프로그램과 충돌하지 않는다. 

 

4) Docker Hub 

이미지 저장소이다. 전 세계 사람들이 만든 이미지를 무료로 공유하는 곳이다. MySQL, Redis, Nginx 등 유명한 소프트웨어는 공식 이미지가 존재하며 그냥 바로 가져다 실행하면 된다. 


3. Dockerfile 

Dockerfile 이란 ?

내가 만든 프로그램을 Docker 이미지로 만드는 설계도 파일이다. 이미지를 만들기 위해 어떤 운영체제를 사용할지, 어떤 프로그램을 설치할지, 어떤 파일을 복사할지 등의 과정을 순서대로 적어두면 `docker build` 명령어를 통해 새로운 이미지를 만들 수 있다. 

 

예를 들어, 아래와 같이 작성했다고 가정해보자. 

FROM openjdk:17
WORKDIR /app
COPY build/libs/kkinikong.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
  • `FROM openjdk:17` : 베이스 이미지 지정 (Java 17이 설치된 환경을 가져다 쓰겠다는 의미이다. 공식 Docker Hub에서 제공하는 openjdk:17 이미지를 기반으로 한다는 의미이다.) 
  • `WORKDIR / app` : 컨테이너 안에서의 작업 디렉토리를  `/app`으로 지정한다. 
  • `COPY build/libs/kkinicong.jar app.jap` : 내 로컬 프로젝트에 있는 `build/libs'/kkinicong.jar` 파일을 컨테이너 안의 `/app/app.jar` 로 복사한다는 의미이다. 이 jar파일이 바로 Spring Boot 빌드 결과물이다. 
  • `ENTRYPOINT ["java", "-jar", "app.jar"]` : 컨테이너가 시작되면 무조건 실행할 명령어이다. 여기서는 `java -jar app.jar` 이 실행되고 이는 Spring Boot 서버가 키는 작업이다. 

4. Docker Compose 

Dockerfile이 하나의 앱을 이미지로 만드는 설명서라면, Docker Compose는 여러 컨테이너를 한꺼번에 실행하고 관리하는 도구이다. 

 

왜 필요할까 ? 

보통 일반적으로 백엔드 서비스에서는 Spring Boot 앱, MySQL, Redis, Nginx 이 있고 이거를 하나하나 docker run으로 띄우려면 옵션도 많고 귀찮다. 그래서 Compose 파일에 서비스 전체 구성을 한 번 정의해두고 `docker-compose up -d` 와 같은 명령어 한 줄로 실행할 수 있다. 

 

기본 문법 

아래는 `handDoc` 프로젝트를 하면서 사용한 `docker-compose.yml` 이다. 

version: "3.8"   # compose 파일 버전 (3.8은 가장 많이 사용되는 최신 안정 버전)

services:        # 실행할 컨테이너(서비스)들을 정의하는 영역
  mongodb:       # 서비스 이름 (컨테이너 네트워크에서 이 이름이 호스트명이 됨)
    image: mongo:6.0              # 사용할 이미지 (mongo 6.0 공식 이미지)
    container_name: handdoc-mongo # 컨테이너 이름
    restart: always               # 컨테이너가 꺼져도 자동 재시작
    ports:
      - "37017:27017"             # 호스트:컨테이너 포트 매핑 (외부에서 접근 가능)
    environment:                 
      MONGO_INITDB_ROOT_USERNAME: ${DOCKER_MONGO_USERNAME}
      MONGO_INITDB_ROOT_PASSWORD: ${DOCKER_MONGO_PASSWORD}
    volumes:
      - mongo_data:/data/db       # 데이터 저장소 (컨테이너 삭제돼도 데이터 유지)
    networks:
      - handdoc-net               # 같은 네트워크에 있는 서비스끼리 통신 가능

  mysql:
    image: mysql:8.0              # 사용할 이미지 (mysql 8.0 공식 이미지)
    container_name: handdoc-mysql
    restart: always
    ports:
      - "53306:3306"              # 호스트:컨테이너 포트 매핑
    environment:
      MYSQL_DATABASE: handdoc     
      MYSQL_ROOT_PASSWORD: ${DOCKER_DB_PASS}  
      TZ: Asia/Seoul              
    command:                      
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - handdoc-net

volumes:   # 데이터 영속성 설정
  mongo_data:
  mysql_data:

networks:  # 네트워크 설정 (서비스끼리 같은 네트워크 안에서 이름으로 통신)
  handdoc-net:

해석 

  • `services` : 컨테이너 단위를 정의하는 블록이다. service: 아래에 적힌 것들이 각 각 하나의 컨테이너가 된다. 
  • `ports` : 호스트의 포트와 컨테이너 내부 포트를 연결하는 설정이다. `"호스트포트:컨테이너포트"` 형식이다. 
  • `volumes` : 컨테이너 안의 데이터를 호스트 저장소에 영구 저장하는 기능이다. 컨테이너를 삭제해도 데이터는 날아가지 않는다. 
  • `networks` : 컨테이너들끼리 서로 통신할 수 있도록 묶어주는 가상 네트워크 

 

실행 방법 

# 컨테이너 전체 실행 
docker-compose up -d

 

'DevOps' 카테고리의 다른 글

Docker로 MySQL 환경 구성해서 팀원들에게 제공하기  (0) 2025.08.05
'DevOps' 카테고리의 다른 글
  • Docker로 MySQL 환경 구성해서 팀원들에게 제공하기
erika0915
erika0915
백엔드 개발자가 되고 싶어요 .
  • erika0915
    erikoding
    erika0915
  • 전체
    오늘
    어제
    • 분류 전체보기 (78)
      • 프로젝트 (13)
        • 끼니콩 (3)
        • 덕메랑 (3)
        • handDoc (7)
        • Haeil (0)
      • Java (9)
        • 클린코더스 (0)
      • Spring (30)
      • Redis (3)
      • CS (7)
        • 운영체제 (3)
        • 컴퓨터구조 (0)
        • 네트워크 (4)
      • DevOps (2)
      • 코딩테스트 (0)
      • Tech (14)
        • TDD (1)
        • 정리 (5)
        • 우테코 (0)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    springboot
    redis
    STT
    운영체제
    파인튜닝
    깃허브
    OS
    CoolSMS
    docker
    promtail
    깃
    지라
    github
    Spring
    자바
    네트워크
    레디스
    스프링부트
    MongoDB
    몽고디비
    Network
    도커
    jira
    git
    coderabbit
    코드레빗
    AI
    TDD
    스프링
    java
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
erika0915
[Docker] Docker의 모든 것

티스토리툴바