[DevOps] Docker

ehekaanldk·2025년 6월 16일

[DevOps]

목록 보기
1/4

리눅스 배포판

  • 리눅스는 커널(핵심)과 기타 구성요소(도구, 라이브러리) 로 구성된다.
  • 동일한 커널 위에서 어떤 도구와 설정을 얹느냐에 따라서 배포판이 달라진다.
    Debian, red hat, ubuntu

리눅스는 커널은 같고, 생태계는 다양한 구조이다.
패키지나 라이브러리에 따라서 배포반의 종류가 다양하다.

OS 는 왜 리눅스로 고정되는가?

  • 리눅스는 오픈소스, 경량, 안정성, 확장성 덕분에 다양한 환경에서 표준
  • 도커 등의 컨테이너 환경은 리눅스 커널을 공유하기 떄문에 니눅스에 최적화 되어 있어 있다.
  • 리눅스는 "동일한 커널 위에 다양한 생태계와 목적에 맞게 맞춤화할 수 있어서"
  • OS 선택 시 특히 서버, 개발, 클라우드, IoT에서는 리눅스가 사실상 표준처럼 사용된다.

소프트웨어(App) 는 OS에 종속된다.

도커에서 격리라는 개념에서
OS는 하드웨어를 관장하는 부분(커널: 안정성에 관한 부분으로 업데이트 관련 크지 않음)과 소프트웨어를 관장하는 부분(여러 라이브러리, 도구 등으로 확장판) 으로 나눈다.

그위에 APP를 동작시키면 어떤 OS인가에 따라서 종속된다.
(jenkins 는 리눅스 배포판 별로 설치환경에 따라서 설정값과 라이브러리가 다 다르다. )
=> App는 주변환경에 영향을 받는다.

과거의 해결방법 : 가상머신 (VM)

과거에 App에 OS까지 묶어서 배포를 하자. => VM

가상머신의 특징

  • 앱 + OS + 필요한 도구까지 전부 포함하여 격리된 가상 환경에서 실행

  • Hypervisor가 하드웨어를 가상으로 분리해 여러 개의 OS를 동시에 실행

  • VM 위에 올라간 OS: Guest OS, 실제 OS: Host OS

  • App입장에서는 현재 운영되고 있는 환경이 가상인지 실제인지 알 수 없다.

  • 독립된 공간에서 혼자 돌고 있어서 오류가 없다.

장점단점
완전 격리, 안정성, 보안느림, 용량 큼, 중복 많음 (OS 전체 포함)

현재의 해결방법 : Docker

OS의 커널은 공유하고, OS의 실행환경(lib, bin)은 컨테이너마다 격리한다.
Docker는 컨테이너 기반 가상화 도구이다.

비교가상머신Docker 컨테이너
커널Guest OS 포함 (별도)Host OS 커널 공유
실행 속도느림빠름
용량큼 (GB 단위)작음 (MB 단위)
부팅 시간수십 초수 초 내외
격리 방식하드웨어 수준운영체제 수준 (namespace, cgroup 등)
  • 격리하면 특정 App이 돌아가도록 하기 좋음
  • 보안상 좋음
  • 문제 생기면 통채로 날려버리면 좋음

격리와 가상화
완전한 가상화를 위해서 docker가 host os를 공유해서 쓴다.
도커는 커널은 공유하고 바이너리와 라이브러리는 각자 격리한다.

  • os 는 커널은 하드웨어와 컨트롤을 담당한다.
  • os의 bin와 lib (배포판) 에서 바이너리와 라이브러리에 영향을 많이 받는다.
  • os의 커널을 모두 공유해서 다 같아야 한다.

도커는 리눅스에서만 사용 가능한가?

docker는 리눅스 커널을 사용해야 하기 때문에

Window/macOS 에서는 내부적으로 리눅스 커널이 없다.
docker를 사용하기 위해서는 가상 리눅스 환경(WSL)을 만들어서 docker를 구동해야한다.

도커 이미지

컨테이너를 실행하기 위한 실행 환경의 설계도

  • ISO와 유사한 개념
  • .iso 는 가상 CD으로 읽기 전용

docker image는 레이어로 이루어져 있다.
잘 만들어 놓은 읽기 전용이고 여러 개의 층을 위에 올려서 구성한다.

도커 이미지를 저장하고 있는 저장소 : 레지스트리 (대표적으로 도커 허브)

도메인 주소 / 저장소 이름 / 이미지 이름 : 이미지 버전

  • 도메인 주소는 생략 가능하고, 기본값은 Docker Hub로 인식
  • 이미지 이름을 생략 불가
  • 이미지 버전은 생략 가능하고, 기본값 latest 인식

Docker.io/library 는 도커이미지의 공식 이미지 Namespace이다.
Azure에서 받으려면 gdhong.azurecr.io/order:1.0

도커 컨테이너

도커 이미지를 실행한 인스턴스

  • 읽기 전용 이미지 + 읽기/쓰기 계층(RW Layer)로 구성
  • 가상의 OS의 환경(bin/lib) 에 App을 올려서 구동한다.
  • 컨테이너는 이미지를 구동하는 구조이다. 일회성으로 한번 만들어 놓고, 안좋으면 날려버리고 다시 만든다.

실행 컴퓨터에서는 pull로 도커 이미지를 다운로드 받아서 하드디스크에 저장된다.
가상 CD를 CD룸에 넣는 것 처럼 run으로 이미지를 메모리에 올려서 구동한다.

도커의 레이어 구조 요약

기존의 만들어진 것을 재활용하는 관점
차이점을 기록하는 형태로 레이어링을 한다.

Base layer

  • Custom layer
  • 어떤 파일을 추가했는지, 삭제했는지를 기록한다.
    => ubuntu + nginx
  • 여러 레이어들을이후에 재활용하는 컨셉으로 운영된다.
  • 도커 이미지가 층층이 쌓여서 도커 컨테이너로 이미지 중에 하나를 컨테이너화 하는데 읽기 전용 - layers을 그대로 가져오고, read/write layer 붙인다.
  • 만들어진 컨테이너 자체를 이미지로 바꿀 수도 있다.

도커 파일

레이어를 만들어서 이미지를 만드는 스크립트
하나의 명령어가 하나의 레이어로 추가된다.

  • FROM : 사용할 기본 이미지(베이스 이미지)

  • RUN : 읽기 전용 이미지 위에 올릴 추가 레이어 (RUN 당 하나의 레이어 추가)

  • WOEKDIR : 작업할 디렉토리 지정

  • COPY : 로컬 파일/폴더를 이미지로 복사(앞에 있는 것을 뒤에 있는 것으로 복사한다. )

  • ENTRYPOINT : 아무 조건을 안주고 이미지를 컨테이너화 시킬 때 구동할 명령어

도커 이미지 명령어

Docker는 백그라우드에서 도는 데몬(서버) 와 사용자가 명령을 보내느 CLI(도커 명령줄 도구) 로 구성된다.

사용자가 docker image 을 입력하면, CLI가 데몬에게 명령을 전달해 작업을 처리한다.

명령어설명
docker images로컬 PC에 다운로드된 이미지 목록 확인
docker pull 이미지명Docker Hub에서 이미지 다운로드
docker rmi 이미지명이미지 삭제 (rmi = remove image)
docker image rm 이미지명위 명령과 동일 (권장 사용 방식)

컨테이너 제어 : docker run
container run 으로 컨테이너 실행
docker run [옵션] [이미지명] [명령어]

--name : 컨테이너 이름을 지정한다.
-d : 백그라운드 실행한다.
-p 8080:80 : 호스트(8080)와 컨테이너(80)를 연결한다.

docker run --name my-nginx -d -p 8080:80 nginx

  • 컨테이너는 메모리에 올라가 실행됨

  • 실행 중인 컨테이너는 docker ps로 확인 가능

  • 중지된 컨테이너는 docker ps -a로 확인 가능

컨테이너를 완전히 제거해야 해당 이미지도 안전하게 삭제 가능함

이미지 빌드 : docker build
도커 빌드는 도커 파일을 이용해서 이미지를 만드는 행위를 bulid라고 한다.

docker build --tag[생성할 이미지의 이름]:[태그 이름].
. 은 도커 파일의 위치이다.
. 만 작성할 경우 해당 명령어를 터미널에서 입력할 때 터미널의 위치가 dockerfile이 있는 위치여야 한다.

이미지 푸시 : docker push
image push는 하드 안에 저장된 이미지를 만천하에 공개하고 싶으면 push한다.
push를 하려면 권한이 있어야 한다.
1. docker login
2. docker tag myapp:1.0 [도커허브 아이디]/myapp:1.0
3. docker push [도커허브 아이디]/myapp:1.0

도커 전체 흐름 요약

  1. Dockerfile 작성 ← 이미지 설계도
  2. docker build ← 이미지 생성
  3. docker run ← 컨테이너로 실행
  4. docker ps ← 컨테이너 상태 확인
  5. docker stop/rm ← 정지 및 삭제
  6. docker push ← 이미지 업로드 (Docker Hub 등)

실습1 : docker 다루기

docker image pull nginx:latest
도커 이미지 nginx:latest를 하드디스크에 다운받는다.

docker run --name my-nginx -d -p 8080:80 nginx:latest
-d 는 데몬으로 백그라운드에서 실행
-p 는 container 내에 실행(80)할 때 내 서버의 포트(8080)와 연결해주는 역할(서버포트와 컨테이너 안에 포트와 연결한다.) -> 8080 -> 80 으로 컨테이너에 들어온다.

docker run --name my-new-nginx -d -p 8081:80 nginx:latest
다른 nginx 컨테이너 페이지를 열어서 동시에 실행 가능하다.

docker container ls로 실행 중인 모든 컨테이너의 목록을 확인할 수 있다.

pip install httpie
http GET http://localhost:8080
http GET http://localhost:8081
으로 서로 다른 것을 확인할 수 있다.

도커 이미지 삭제하기

docker 이미지를 삭제할 때는 해당 이미지를 사용하는 컨테이너를 먼저 정리 해야한다.

docker container stop [컨테이너명]
docker container ls -a 으로 stop된 결과를 확인할 수 있다.

docker container rm [컨테이너명]
docker image rm [이미지명]
컨테이너 이름이나 컨테이너 ID을 넣어서 정지할 수 있다.

도커 이미지 만들기

/Docker/index.html

<html>
<body>
<center>
<br/></br>
<img src="https://raw.githubusercontent.com/acmexii/demo/master/materials/smile.jpg">
<br/></br>
<h1> Hi~ My name is Hong Gil-Dong...~~~ </h1>
</center>
</body>
</html>
</center>
</body>
</html>

/Docker/Dockerfile

FROM nginx
COPY index.html /usr/share/nginx/html/

만든 도커 이미지를 빌드한다.
docker build -t [도커허브 아이디]/welcome:v1 .

도커허브에 만든 도커이미지를 push한다.
docker login

docker push [도커허브아이디]/welcome:v1

docker run --name=welcome -d -p 8080:80 [도커허브아이디]/welcome:v1


실습2 : spring boot의 app을 docker image로 만들기

애플리케이션 빌드 : mvn package

mvn spring-boot:run 했던거를 mvn package 으로 해서
컴파일 -> test 코드 컴파일 -> 실제 test -> jar로 만들기 을 자동으로 수행한다.
해당 과정의 결과가 target/ 폴더에 들어가게 된다.

실제 실행을 할 수 있다.
✅ 결과
java -jar target/inventory-0.0.1-SNAPSHOT.jar 으로 동일하게 mvn spring-boot:run 처럼 실행된다.

  • .jar 는 독립 실행 가능한 spring-boot의 앱이다.
  • snapshot을 개발중인 버전을 의미한다.

도커 이미지 생성

/inventory/Dockerfile

FROM openjdk:15-jdk-alpine
COPY target/*SNAPSHOT.jar app.jar
EXPOSE 8080
ENV TZ=Asia/Seoul
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ENTRYPOINT ["java","-Xmx400M","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar","--spring.profiles.active=docker"]
  • FROM 아래에는 베이스 이미지를 작성한다.
  • COPY 뒤에는 target/*SNAPSHOT.jar 를 복사해서 app.jar 에 붙인다. => layer 하나 생성되어 붙음
  • 이 이미지는 Spring Boot 앱이 포함된 경량 자바 실행 환경이 된다.

터미널에서 order, gateway 폴더로 이동해서
각각의 Dockerfile이 있는 위치에서 아래를 실행한다. (cd order, cd gateway 각각에서 실행)

mvn package 
docker build -t [dockerhub ID]/inventory:[오늘날짜] .     
docker push [dockerhub ID]/inventory:[오늘날짜]  


비교

Dockerfile만으로 이미지 생성 및 실행 VS java 프로젝트를 먼저 mvn package로 빌드 후에 Docker 이미지 생성

방법 1 : 바로 Dockerfile -> build -> run -> push
dockfile 내부에 직접 빌드가 있으면 그때 실행된다.

FROM nginx:latest
COPY ./index.html /usr/share/nginx/html

방법 2 : mvn package 후 dockerfile -> build -> push
dockerfile 을 실행하기 전에 Jar 를 생성한다.

FROM openjdk:17
COPY target/myapp.jar /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
구분방식 1방식 2
개요Dockerfile만으로 이미지 생성 및 실행Java 프로젝트를 먼저 mvn package로 빌드 후 Docker 이미지 생성
JAR 파일 생성 시점Dockerfile 내부에서 직접 빌드 (있다면)Dockerfile 실행 전에 미리 JAR 생성 (mvn package)
장점Docker 하나로 모든 작업 처리 가능 (CI/CD에 적합)빌드 결과를 미리 확인 가능, 실패 시 빠르게 디버깅
예시 대상정적인 nginx 같은 이미지Java/Spring Boot 앱과 같이 빌드가 필요한 프로젝트

0개의 댓글