1. Docker 주요 명령어
1) 이미지 관련
docker pull <이미지명> # 이미지 다운로드
docker images # 로컬 이미지 목록 보기
docker rmi <이미지ID> # 이미지 삭제
docker history <이미지명> # 해당 이미지의 히스토리
2) 컨테이너 실행(run)
docker run <이미지명> # 컨테이너 실행
docker run -d <이미지명> # 백그라운드 실행
docker run -it <이미지명> bash # 컨테이너 내부 접속
docker run -p 8080:80 <이미지명> # 포트 매핑
docker run -v 호스트:컨테이너 # 볼륨 마운트
예:
docker run -d -p 9999:80 -v /home/html:/usr/local/apache2/htdocs httpd
docker run -d -p 9999:80 --name web myweb
3) 컨테이너 관리
docker ps # 실행 중인 컨테이너
docker ps -a # 모든 컨테이너
docker stop <ID> # 컨테이너 중지
docker start <ID> # 다시 실행
docker restart <ID> # 재시작
docker rm <ID> # 컨테이너 삭제
docker logs <ID> # 로그 확인
# 컨테이너와 컨테이너 연결
# 1) MySQL 컨테이너 실행 (포트 개방 없이 내부에서만 실행)
docker run --rm -d --name mydb \
-v /home/ubuntu/mssqldata:/var/lib/mysql \
mysqldb
→ 설명
- --rm : 컨테이너가 종료되면 자동 삭제
- -d : 백그라운드 실행
- --name mydb : 컨테이너 이름을 mydb로 지정
- -v /home/ubuntu/mssqldata:/var/lib/mysql :
MySQL 데이터 저장소를 호스트에 영구 저장(데이터 유실 방지)
- 포트(-p)를 안 썼기 때문에 외부에서는 접속할 수 없음
= 오직 “다른 컨테이너들만” MySQL에 접근 가능
- mysqldb : 내가 빌드한 MySQL Docker 이미지 이름
# 2) Jupyter Notebook 컨테이너가 MySQL 컨테이너에 연결 (--link)
docker run --rm -d -p 9999:80 \
-v /home/ubuntu/dev:/home/jovyan/work \
--link mydb:myjupyterdb \
jupyter/datascience-notebook
→ 설명
- --rm : 컨테이너 종료 시 자동 삭제
- -d : 백그라운드 실행
- -p 9999:80 : 호스트 9999 → 컨테이너 80포트로 접근 가능
(브라우저에서 http://IP:9999 접속)
- -v /home/ubuntu/dev:/home/jovyan/work :
Jupyter의 작업 폴더를 호스트 디렉토리와 공유
- --link mydb:myjupyterdb :
Jupyter 컨테이너에서 "myjupyterdb" 라는 이름으로
MySQL 컨테이너(mydb)에 접근할 수 있게 연결
예) mysql -h myjupyterdb -u root -p
- jupyter/datascience-notebook : Jupyter 공식 이미지
# 요약
- MySQL 컨테이너는 외부 포트를 열지 않고 내부에서만 구동
- Jupyter Notebook 컨테이너는 --link 옵션으로 MySQL에 직접 접속 가능
- 따라서 Jupyter는 DB를 쓸 수 있지만 외부에서 MySQL로 접속할 수 없음
- Jupyter는 -p 9999:80 으로 외부 브라우저 접근 가능
4) 컨테이너 내부 진입
# 컨테이너 내부 진입
docker exec -it <container> /bin/bash
docker exec -it <container> /bin/sh
# 컨테이너 내부에 접근하여 현재 호스트 폴더로 000-default.conf를 복사함
docker cp web:/etc/apache2/sites-available/000-default.conf ./
# 현재 호스트 000-default.conf 파일을 컨테이너 내부에 붙여넣음
docker cp 000-default.conf web:/etc/apache2/sites-available/000-default.conf
# 컨테이너 내부의 변경사항을 이미지 파일로 생성
docker commit -m <컨테이너 ID 또는 이름> <이미지 이름>
# 기존의 이미지와 현재 컨테이너 이미지를 비교하여 다른점을 출력
docker diff <컨테이너명>
A는 추가, D는 삭제, C는 변경
5) 도커 시스템 정리
docker system df # 디스크 사용량
docker system prune # 미사용 컨테이너/이미지 제거
2. Dockerfile 작성 방법
## 기본구조
# FROM: 어떤 환경(베이스 이미지)에서 시작할지 정의 / 이미지만 적으면 자동 latest
FROM python:3.10-slim
FROM alpine
# LABEL: key=value 형식으로 메타데이터를 넣을 수 있음
LABEL description="Python 기반 토큰 클리너 서비스"
LABEL maintainer="홍길동 <gildong@example.com>"
LABEL version="1.0.0"
docker inspect myweb
...
"Labels":{
"author": "ㅇㅇㅇ"
}
...
# COPY: 호스트 파일을 도커 컨테이너 내부로 복사
COPY clean_tokens.py /app/clean_tokens.py
COPY ./DEV /usr/local/apache2/htdocs
# RUN: 이미지 빌드 과정에서 필요한 명령 실행
RUN pip install schedule requests
RUN apt-get install
RUN apt-get install -y apache2 apt-utils
# CMD: 컨테이너 실행 시 실행할 기본 명령
3가지 예시
Docker 공식에서 추천하는 방식
CMD ["python", "clean_tokens.py"]
쉘기반
CMD python clean_tokens.py
ENTRYPOINT는 반드시 실행해야하는 '메인 명령', CMD는 '인자' 역할을 함
ENTRYPOINT ["python"]
CMD ["clean_tokens.py"]
docker inspect myweb
...
"Cmd":[
"/bin/sh",
"-c",
"httpd-foreground"
]
...
# Dockerfile의 CMD 명령 덮어쓰기
docker run -d -p 9999:80 --name web myweb /bin/sh -c httpd-foreground
# EXPOSE: 컨테이너가 사용하는 포트를 문서화(외부 오픈 아님)
EXPOSE 8080
# ENV: 환경변수로 활용
ENV MYSQL_ROOT_PASSWORD=password
ENV MYSQL_DATABASE=dbname
# WORKDIR: 이후 명령어가 실행될 작업 디렉터리 설정
WORKDIR /app
1) 이미지 빌드
docker build <옵션> Dockerfile_path
<옵션 예시>
docker build --tag myimg .
-t 또는 --tag: 이미지의 이름 설정
docker build --tag myimg2 -f Dockerfile2 .
-f: Dockerfile을 지정함
docker build --tag myimg3 -f Dockerfile2 --pull=true
--pull: 해당 옵션은 이미지 생성시마다 새로 다운로드 받으라는 옵션
3. Dockerfile 실전 예시
(1) Apache 웹서버 + HTML
# RUN 할 필요 없이 COPY만 해도 동작함
FROM httpd:latest
COPY ./html/ /usr/local/apache2/htdocs/
빌드: docker build -t my-apache .
실행: docker run -d -p 9999:80 my-apache
(2) Node.js 서버 이미지 만들기 (프론트/백엔드 둘 다 가능)
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
(3) Spring Boot JAR 실행용 Dockerfile
FROM eclipse-temurin:17-jdk
WORKDIR /app
COPY build/libs/myapp.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
4. docker-compose
# 주로 services(필수), volumes(선택)만 쓰임
# 다른 옵션 networks, secrets, configs, depends_on, healthcheck, deploy 등등
services: # 실행할 서비스(컨테이너) 목록
backend: # 내가 정한 서비스(컨테이너) 이름
build: # Dockerfile을 이용해 이미지 빌드
context: . # 현재 디렉토리를 빌드 컨텍스트로 사용
dockerfile: Dockerfile # 빌드할 도커파일 지정
ports:
- "8080:8080" # 호스트 8080 → 컨테이너 8080 포트 매핑
env_file:
- .env # 환경변수 파일(.env) 사용
depends_on:
- db # db 서비스가 먼저 시작되도록 지정
restart: always # 컨테이너 종료 시 자동 재시작
networks:
- appnet # appnet 네트워크 연결
volumes:
- ./logs:/app/logs # 로컬 logs → 컨테이너 /app/logs 마운트
- ./config:/app/config # 로컬 config → 컨테이너 /app/config 마운트
db: # 내가 정한 서비스(컨테이너) 이름
image: postgres:15 # PostgreSQL 15 이미지 사용
environment:
POSTGRES_PASSWORD: 1234 # Postgres 초기 비밀번호 설정(환경변수)
volumes:
- pgdata:/var/lib/postgresql/data # 데이터 저장 볼륨 지정
restart: always # DB 컨테이너 자동 재시작
networks:
- appnet # 같은 네트워크 사용
volumes: # Docker 볼륨 정의
pgdata: # 이름 있는 볼륨(데이터 영속성)
networks: # Docker 네트워크 정의
appnet: # 서비스들이 공유할 네트워크 이름
driver: bridge # 로컬 개발에서 기본적으로 사용하는 bridge 네트워크
# 실행 방법
docker compose up -d
→ yml에 적힌 web + db 컨테이너가 동시에 실행됨
# 중지
docker compose down
→ yml에 적힌 컨테이너 중지
# 종료
docker compose down
→ 두 개 모두 종료 및 네트워크 제거
# logs 확인
docker compose logs -f
→ 여러 컨테이너 로그를 한 번에 확인 가능
# .dockerignore 파일을 통해 COPY할 파일을 제외할 수 있음