ssuperjun 님의 블로그
[스터디1] Docker 본문
Docker란?
도커(Docker)는 애플리케이션을 격리된 환경(컨테이너, Container)에 패키징하여, 어느 환경에서도 동일하게 실행할 수 있게 하는 오픈 소스 소프트웨어 플랫폼
Docker(Container)의 필요성


하나의 서버에서 여러 애플리케이션을 띄우는 경우, 버전 충돌 문제 발생
Docker로 애플리케이션을 격리시키면, 버전 충돌 문제 해결
서비스마다 다양한 하드웨어에 따른 다양한 소프트웨어 종류 버전 요구
한 앱이 여러 환경에 호환 or 한 환경이 여러 앱에 호환되는 것 필요
컨테이너를 사용하면 개발 및 배포 과정에서 환경이 일관되게 유지됨
어떤 환경에서도 버전을 맞춰 애플리케이션이 동일하게 실행되도록 함
요청 많아지면 scale out(작업 처리할 어플리케이션 공간 늘리기) 하기에도 용이하다.
*scale out(수평적 증가): 트래픽 및 작업 부하 증가 시 시스템 리소스를 추가 -> 성능 유지
*scale up(수직적 증가): 시스템 리소스를 업그레이드(gpu, ram 등 추가 혹은 개선) -> 성능 유지
컨테이너란? 도커 이미지란?
컨테이너: 애플리케이션을 실행하는 데 필요한 모든 종속성을 포함하는 경량 소프트웨어 패키지
종속성: 시스템 라이브러리, 외부 코드 패키지 및 기타 운영 체제 수준 애플리케이션 등이 있지만, 컨테이너에 포함된 종속성은 운영 체제보다 고수준인 편
이미지: 소스코드, 라이브러리, 기타 파일(애플리케이션 실행에 필요한 모든 파일)을 모아놓은 불변(immutable) 파일
요약하면 이미지 파일 = 프로그램을 실행하는 데 필요한 모든 파일을 포함
이미지를 실행시켜 인스턴스화 한 것이 컨테이너이다.
빌드로 이미지 만들고, 다른 환경에서 이미지 실행하면 배포 완료
Virtual Machine vs. Container

Virtualization 예시: Virtualbox
한 하드웨어 위에 VM 설치해 여러 OS 운영 가능
각 VM이 사용자라고 가정하면
여러 사용자가 하나의 물리적 컴퓨팅 자원을 효율적으로 나눠쓸 수 있음
사용자는 VM을 통해 논리적으로 분리되어 독립적으로 운영할 수 있음
하이퍼바이저는 여러 게스트os를 분리하고 리소스를 할당함
virtualization은 migration에 이점이 있음 - 사용자가 기존 피지컬 머신이 바뀐줄도 모르게 migration 가능
그래서 유지보수 및 시스템 리소스 최적화
자원 할당 시 time sharing으로 효율적 할당 가능 - 더 쓰는 애 더 주고 덜 쓰는 애 덜 주고
유연함
각 사용자별 독립성 보장 - 보안
같은 피지컬 컴퓨터를 공유하기 때문에 부하 예측 실패 시 성능 저하
가상화는 분리 통합 이주에 유리
os 구동에 시간 소요
io 오버헤드 발생 - 하나의 하이퍼바이저 거쳐야 하므로
Container
하나의 물리적 컴퓨팅 자원 위에 여러 앱 구동
한 피지컬 하드웨어, os 공유, 독립성 보장
container engine이 각 앱에 리소스 할당
컨테이너 분리 위한 2가지 기술
namespace - 한 os 시스템을 분할
cgroup - infrastructure(피지컬 컴퓨터)의 리소스 관리. 여러 프로세스가 한 피지컬 컴퓨터에 접근할 때 리소스 충돌 방지
단점
호스트 os 공유하므로 os 손상 시 모든 컨테이너가 문제 발생
모든 컨테이너가 동일 커널 공유하므로 보안 문제 존재
VM에 비해 자원이 완벽히 독립적으로 통제되지 않을 수 있음(상대적인 것일 뿐이지, 컨테이너도 충분히 독립성 보장됨)
쿠버네티스 = 항해사 그리스어
여러 container랑 도커들 orchestration
웹 복잡성 증가에 따른 수많은 요청 효율적인 처리 필요
동일 설정 가진 여러 서버 관리 어려워짐
모든 컨테이너 관리 중요 - 오류 디버깅 모니터링
오토 스케일링, 리소스 제어, 확장성, 휴대성
컨테이너 - 다양한 소프트웨어 한 서버에서 효율적으로 동작 가능
도커 - 컨테이너 관리. 앱들 컨테이너화해 배포 및 실행 가능
쿠버네티스 - 여러 서버에 걸쳐있는 도커 컨테이너들을 조율 자동화
도커 설치 명령어 모음
sudo apt-get update
도커 실행 명령어 모음
# sudo 없이 docker 실행하기
sudo usermod -aG docker {username}
# docker 실행
sudo service docker run start
# docker 중단
sudo service docker stop
도커 명령어 종류
# 이미지 리스트
docker images
# 실행
docker run
# 예시: docker run –it –-name webserver –p 80:80 rmkuma/oss_week9:0.1 /bin/bash
# -t : 특정 이미지를 지정하는 옵션
# -i : 현재 터미널 창에 attach하여 상호작용할 수 있게 만드는 옵션 (-it 로 같이 사용함)
# -d : detach한 상태로 실행하여 background에서 container를 실행하는 옵션
# --name : 생성되는 container의 이름을 정할 수 있는 옵션
# --cpu-shares, --gpus, --memory : container가 사용할 수 있는 하드웨어를 제한하는 옵션
# =v : volume(현재 서버의 특정 디렉토리)를 연결하여 container 내부에서 접근하는 옵션
# -p : 호스트의 네트워크 포트를 container 내부의 port와 연결해주는 옵션
# -net : 특정 네트워크를 사용하여 container 사이의 통신을 가능하게 해주는 옵션
# 컨테이너 리스트
docker ps
# 도커파일 사용해 빌드
docker build
# docker hub 사이트 이용
docker pull
docker commit
docker push
도커 volume: 호스트 내에 연결할 컨테이너 공간을 할당. 호스트 내 파일은 도커 컨테이너 파일과 연결되어 있음(얕은복사 느낌 - 여기서 수정하면 저기서도 반영됨)
도커 네트워크: 호스트(서버)와 컨테이너를 포트 지정해서 연결
데이터 영속성 = 컨테이너가 중지되거나 삭제되어도 데이터 유지되도록 도커 볼륨으로 연결
볼륨 마운트하는 노드들이 많아지면, 의존성 높아지고 관리해야 될 게 많아짐
모든 걸 루트 권한으로 수행하도록 하면 안됨 - 데이터 삭제 작업 유의
도커 파일의 필요성
도커 이미지는 용량도 많고, 수정하기도 어려움
→ 몇kb짜리 도커 파일로 도커 빌드하면 도커 이미지가 뚝딱 생성됨
수정과 배포의 편의성
도커파일 기본 명령어
FROM: 기본이 되는 Docker Image를 지정
ADD & COPY: Host의 파일(src)이나 디렉토리를 Docker 이미지 내부의 파일 시스템(dest)으로 복사
ARG: Build 시에 사용될 variable을 넘겨 받는다.
CMD: 컨테이너가 시작될 때 실행할 명령을 지정(ex. “/bin/bash”)
ENTRYPOINT: 컨테이너가 시작될 때 항상 실행되어야 하는 명령을 설정(CMD보다 우선시)
ENV: 환경변수 지정
EXPOSE: Docker 내부에서 특정 port로 listen할 때 사용됨, 기본 protocol은 TCP
# 그러나, 어차피 docker run 시 –p를 통해 host의 port와 mapping 해야 하기 때문에 (덮어짐) 실효성은 없고, Dockerfile의 가시성(무슨 port, protocol)을 위한 명령어
RUN
WORKDIR: docker가 실행되는 디렉토리 경로
VOLUME: 볼륨(workspace) 생성
도커파일을 만들 땐, 컨테이너를 임시로 실행하고 내부에서 필요한 명령어들을 하나씩 시험하는 식으로 인터랙티브하게 도커파일을 구성하는 게 중요하다. 이미지를 한번 빌드하고 실행하는 데 많은 시간이 소요되기 때문
Docker Compose: 여러 개의 컨테이너를 한번에 묶어서 띄울 수 있다.
예를 들어 Apache Hadoop 다중 노드 클러스터(Master + 3 Worker)를 구축할 때 docker compose를 사용할 수 있다.
docker run은 명령어가 길다.
docker-compose.yml 예시
version: '3.3'
services:
hadoop:
build:
context: .
dockerfile: Dockerfile
container_name: hadoop-single-node-container
ports:
- "9870:9870" # HDFS NameNode 웹 UI 포트
volumes:
- ./hadoop-data/dfs/name:/opt/hadoop_tmp/dfs/name
- ./hadoop-data/dfs/data:/opt/hadoop_tmp/dfs/data
tty: true # bash 셸 접근
컨테이너 초기화 후 재시작 명령어
# 모든 컨테이너 정리
docker-compose down -v # -v 옵션은 컨테이너 내 영속 데이터 삭제
sudo rm -rf {볼륨 마운트된 디렉토리 경로}
docker image prune -f
docker volume prune -f
docker network prune -f
docker system prune -af # 이건 docker images, ps 다 없애버리는 명령
# 빌드
docker-compose build 혹은 docker-compose build --no-cache
docker-compose up --build -d # 빌드와 실행 한번에
# 실행
docker-compose up -d # 백그라운드로 실행
# 마스터 컨테이너 접속(컨테이너 잘 동작하나 확인)
docker exec -it master /bin/bash
Hadoop 다중 노드 클러스터 구축, HDFS 및 MapReduce 실습 당시 도커파일 구성 순서 예시
임시로 실행한 컨테이너 내부에서 필요한 명령어들을 하나씩 시험하고, 성공한 명령어들만 도커파일에 반영함
1단계: 작업 디렉토리 설정
cd /softeer/data_engineering_course_materials/missions/W3/M1
mkdir hadoop-docker && cd hadoop-docker
2단계: 임시 Ubuntu 기반 컨테이너 띄우기
docker run -it --name temp-hadoop ubuntu:20.04 /bin/bash
3단계: 컨테이너 내부에서 필요한 패키지 설치
apt update && apt upgrade -y
apt install -y openjdk-11-jdk wget ssh rsync net-tools vim curl iputils-ping
4단계: Hadoop 설치 및 환경 설정 (컨테이너 내부)
#Hadoop 다운로드
wget https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz
#압축 해제 및 이동
tar -xzf hadoop-3.3.6.tar.gz
mv hadoop-3.3.6 /opt/hadoop
#환경 변수 설정
echo 'export HADOOP_HOME=/opt/hadoop' >> ~/.bashrc #Hadoop이 설치된 디렉토리 경로를 지정. Hadoop 명령어들이 어디에 설치되었는지 시스템이 앎.
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64' >> ~/.bashrc #Java 11이 설치된 경로를 설정
echo 'export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin' >> ~/.bashrc #기존 PATH에 Hadoop의 실행파일 경로들을 추가해 터미널 어디서든 hadoop, start-dfs.sh 같은 명령어 실행
source ~/.bashrc #.bashrc 파일을 즉시 적용해 현재 터미널 세션에 반영
#정상 작동 테스트
hadoop version
5단계: Hadoop 설정파일 구성
cd /opt/hadoop/etc/hadoop/
core-site.xml 설정: Hadoop의 전반적인 기본 설정을 정의합니다. 특히, 파일 시스템의 기본 주소를 지정합니다.
hdfs-site.xml 설정: HDFS(Hadoop Distributed File System)의 데이터 저장 위치와 복제 정책 등을 설정합니다.
mapred-site.xml 설정: MapReduce 프레임워크에 대한 실행 방식을 설정
yarn-site.xml 설정: YARN (Yet Another Resource Negotiator)의 기본 구성을 설정. 즉, Hadoop 클러스터의 자원 할당과 실행 방식 설정
6단계: namenode 포맷
hdfs namenode -format
7단계: 서비스 수동 실행 테스트
테스트 환경이므로 start-dfs.sh 대신 수동으로 데몬 실행
hdfs --daemon start namenode
hdfs --daemon start datanode
start-dfs.sh
#컨테이너 내부에서 ssh 서버를 구동해야 함
#jps 명령어로 프로세스 확인 (namenode, datanode 떠야 정상)
jps
#예시 출력:
#12345 NameNode
#12346 DataNode
8단계: 컨테이너 종료 후 Dockerfile 구성
[고려사항]
설치 시 asia/seoul 부분 자동 선택되게 수정
root로도 실행하도록 환경변수 지정
$HADOOP_HOME/etc/hadoop/hadoop-env.sh 파일을 열고, JAVA_HOME을 명시적으로 설정
설정파일 4개 core-site.xml, hdfs-site.xml, mapred-site.xml, yarn-site.xml 파일 생성
entrypoint.sh 생성해서, 초기 설정(namenode 포맷) + 데몬 실행
Dockerfile
FROM ubuntu:20.04
#환경 설정
ENV DEBIAN_FRONTEND=noninteractive
ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
ENV HADOOP_VERSION=3.3.6
ENV HADOOP_HOME=/opt/hadoop
ENV PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
#패키지 설치 및 시간대 설정
RUN apt update && apt upgrade -y \
&& apt install -y openjdk-11-jdk wget ssh rsync net-tools vim curl iputils-ping tzdata \
&& ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime \
&& dpkg-reconfigure -f noninteractive tzdata
#Hadoop 설치
RUN wget [https://downloads.apache.org/hadoop/common/hadoop-${HADOOP_VERSION}/hadoop-${HADOOP_VERSION}.tar.gz](https://downloads.apache.org/hadoop/common/hadoop-$%7BHADOOP_VERSION%7D/hadoop-$%7BHADOOP_VERSION%7D.tar.gz) \
&& tar -xzf hadoop-${HADOOP_VERSION}.tar.gz \
&& mv hadoop-${HADOOP_VERSION} $HADOOP_HOME \
&& rm hadoop-${HADOOP_VERSION}.tar.gz
#환경변수 설정 파일 내 JAVA_HOME 지정
RUN echo "export JAVA_HOME=$JAVA_HOME" >> $HADOOP_HOME/etc/hadoop/hadoop-env.sh
#Hadoop 설정 파일 복사 (작성자가 따로 준비해야 함)
COPY core-site.xml $HADOOP_HOME/etc/hadoop/core-site.xml
COPY hdfs-site.xml $HADOOP_HOME/etc/hadoop/hdfs-site.xml
COPY mapred-site.xml $HADOOP_HOME/etc/hadoop/mapred-site.xml
COPY yarn-site.xml $HADOOP_HOME/etc/hadoop/yarn-site.xml
#데이터 디렉터리 생성
RUN mkdir -p /opt/hadoop_tmp/dfs/name /opt/hadoop_tmp/dfs/data
#포맷 및 데몬 실행용 기본 스크립트 복사
COPY [entrypoint.sh](http://entrypoint.sh/) /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
9단계: Docker 이미지 빌드 및 테스트
docker build -t hadoop-single-node .
docker run -it -p 9870:9870 --name hadoop-single-node-container hadoop-single-node
(docker run -it --name hadoop-single-node-container hadoop-single-node)
#컨테이너에서 나왔다면 다시 접속
docker exec -it hadoop-single-node-container /bin/bash
10단계: HDFS 동작 테스트
#디렉토리 생성
hdfs dfs -mkdir -p /user/root
#샘플 파일 업로드
echo "Hello Hadoop" > test.txt
hdfs dfs -put test.txt /user/root/
#업로드 확인
hdfs dfs -ls /user/root/
#파일 읽기
hdfs dfs -cat /user/root/test.txt
#접속 주소
http://localhost:9870/
#HDFS 웹 UI 확인(컨테이너 실행)
docker run -it -p 9870:9870 --name hadoop-single-node-container hadoop-single-node
Docker 기반의 Apache Spark Standalone 클러스터를 구축하고, Spark 작업을 실행하며 그 결과를 검증 - Spark Master 1개, Worker 2개 구성. Spark Web UI를 통한 작업 모니터링. PySpark 기반 π 추정 작업 제출
테스트용 컨테이너 생성 (인터랙티브 환경 구축)
docker run -it -p 8080:8080 -p 7077:7077 --name spark-test ubuntu:22.04 /bin/bash
apt update && apt install -y curl wget git build-essential software-properties-common net-tools python3 python3-pip
python3 —version
apt install -y openjdk-17-jdk
java -version
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-arm64
export PATH=$PATH:$JAVA_HOME/bin
cd /opt
wget https://dlcdn.apache.org/spark/spark-4.0.0/spark-4.0.0-bin-hadoop3.tgz
tar -xzf spark-4.0.0-bin-hadoop3.tgz
echo 'export SPARK_HOME=/opt/spark' >> ~/.bashrc
echo 'export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin' >> ~/.bashrc
source ~/.bashrc
# 심볼릭 링크 생성
ln -s /opt/spark-4.0.0-bin-hadoop3 /opt/spark
#Hostname 확인
Hostname
#결과를 worker 실행 시 반영
$SPARK_HOME/sbin/start-master.sh
$SPARK_HOME/sbin/start-worker.sh spark://df31b403bcb3:7077
http://localhost:8080/ 확인
#스파크 예제
$SPARK_HOME/bin/spark-submit --master spark://df31b403bcb3:7077 $SPARK_HOME/examples/src/main/python/pi.py 10
#결과 확인
Pi is roughly 3.137680
#http://localhost:8080/ Web UI의 Completed Applications 섹션에도 작업이 기록됨
도커파일 만들고 빌드 및 실행 테스트
docker build -t spark:4.0.0 .
docker run -it -p 8080:8080 -p 7077:7077 --name spark-test2 spark:4.0.0'인턴' 카테고리의 다른 글
| [과제6-3] 로컬 및 컨테이너 실행 테스트: MyMon Dev환경 세팅(웹 소스코드 도커라이징) (0) | 2026.01.28 |
|---|---|
| [과제6-2] 환경변수 분리: MyMon Dev환경 세팅(웹 소스코드 도커라이징) (0) | 2026.01.27 |
| [과제6-1] 웹 띄우기: MyMon Dev환경 세팅(웹 소스코드 도커라이징) (0) | 2026.01.21 |
| [과제5-6] DB 모니터링 프로그램 Python 변환 6편: 추가 구현, 조사 (1) | 2026.01.19 |
| [과제5-5] DB 모니터링 프로그램 Python 변환 5편: Python 의존성 패키지 설치, 코드 실행 테스트 (0) | 2026.01.17 |