⚙️ Docker 전체 구조와 실행 흐름 정리
도커(Docker)는 이제 거의 모든 개발 환경에서 필수처럼 여겨지는 기술입니다.
그런데 처음 접하면 이런 의문이 들죠:
“이미지를 만든다는 게 뭔데?”
“컨테이너는 실행되면 뭐가 다르지?”
“왜 docker-compose까지 있어야 하지?”
이 글에서는 Docker의 전체 구조와 실행 흐름을 실전 위주로 정리해보겠습니다.
✅ 전체 실행 흐름 요약
Docker는 기본적으로 아래의 흐름으로 작동합니다.
Dockerfile → docker build → Image → docker run → Container → docker-compose
즉, 코드를 감싸 실행 가능한 이미지를 만들고,
그걸 실행시켜 컨테이너로 띄우고,
여러 컨테이너가 필요할 경우 Compose로 묶어서 관리합니다.
🧾 Dockerfile
이미지를 생성해주는 명령어 스크립트 파일
Dockerfile은 하나의 어플리케이션을 컨테이너로 만들기 위한 설계도입니다.
예시: Spring Boot Dockerfile
FROM openjdk:17-jdk
WORKDIR /app
COPY build/libs/backendProject-0.0.1-SNAPSHOT.jar /app/backendProject-0.0.1-SNAPSHOT.jar
CMD ["java", "-jar", "/app/backendProject-0.0.1-SNAPSHOT.jar"]
주요 명령어 설명
명령어설명
| FROM | 사용할 베이스 이미지 지정 |
| WORKDIR | 작업 디렉토리 설정 (없으면 자동 생성됨) |
| COPY | 호스트 → 컨테이너로 파일 복사 |
| CMD | 컨테이너 실행 시 기본 명령 지정 |
| RUN | 의존성 설치 등 빌드 중 필요한 명령 실행 |
| ENV | 환경 변수 설정 |
| EXPOSE | 컨테이너가 열어줄 포트 지정 |
| ENTRYPOINT | CMD와 유사하나 고정 명령 지정에 더 적합 |
🧱 docker 컨테이너
이미지를 실행해서 만든 실행 인스턴스
docker run --name backend -d -p 8050:8080 --network my-network backend
옵션 설명
옵션설명
| --name | 컨테이너 이름 지정 |
| -d | 백그라운드 실행 |
| -p | 포트 매핑 (호스트:컨테이너) |
| --network | 특정 네트워크에 연결 |
| 마지막 인자 | 사용할 이미지 이름 |
🛠 도커 이미지 / 컨테이너 관리 명령어
명령어설명
| docker ps | 실행 중인 컨테이너 목록 |
| docker ps -a | 중지된 것 포함 전체 목록 |
| docker images | 보유 중인 이미지 목록 |
| docker stop [ID] | 컨테이너 중지 |
| docker rm [ID] | 컨테이너 삭제 |
| docker rmi [ID] | 이미지 삭제 |
| docker exec -it [컨테이너] bash | 컨테이너 내부 진입 |
| docker logs [ID] | 로그 출력 |
💽 Volume
컨테이너가 종료되면 데이터도 사라진다?
그래서 Volume으로 로컬 디렉토리와 연결해야 한다.
docker run -v /host/path:/container/path ...
볼륨의 역할
- 컨테이너 내부에서 생성되는 데이터를 외부로 저장
- DB, 로그, 설정 파일 등의 영속성 보장
- 재시작해도 데이터가 유지됨
🌐 Network
컨테이너끼리 서로 통신하려면?
→ 같은 네트워크에 묶어야 함
docker network create app-network
docker run --network app-network ...
- 각 컨테이너는 격리되어 있음
- localhost는 자신의 컨테이너만 바라봄
- --network로 연결해줘야 다른 컨테이너와 통신 가능
🧩 Docker Compose
여러 개의 컨테이너를 한번에 묶어서 관리하기 위한 도구
docker run을 반복할 필요 없이,
docker-compose.yml 파일 하나로 구성부터 실행까지 가능!
🗂 docker-compose 전체 구조 예시
version: "3.8"
services:
backend:
container_name: backend
build:
context: ./backend
image: backend
ports:
- "8050:8080"
networks:
- app-network
environment:
- SPRING_PROFILES_ACTIVE=prod
volumes:
- ./backend/logs:/logs
depends_on:
- mysql
mysql:
container_name: mysql
image: mysql:8
ports:
- "3307:3306"
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=filmus
- MYSQL_USER=user
- MYSQL_PASSWORD=pass
volumes:
- mysql-data:/var/lib/mysql
networks:
- app-network
nginx:
container_name: nginx
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- backend
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mysql-data:
⚙️ docker-compose 명령어 정리
명령어설명
| docker-compose up -d | 컨테이너 전체 실행 |
| docker-compose down | 컨테이너 전체 종료 및 정리 |
| docker-compose logs | 전체 로그 확인 |
| docker-compose ps | 실행 중인 컨테이너 확인 |
| docker-compose restart [서비스] | 서비스 재시작 |
다음 글에서는 nginx의 역할과 여러 서버를 실행 후 nginx로 서버 요청을 분산시켜
로드밸런싱을 통한 트래픽을 분산하고 보안을 강화에 대해 써보겠다.
