[Docker] Docker 고급 사용법

콩퓨터·2025년 1월 23일

CI/CD

목록 보기
9/10

Docker 고급 사용법


Dokcer Volume

Docker VolumeDocker Container 실행하면서 데이터를 보존한다.

왜 Volume을 사용하는 걸까 ?

데이터가 남아있게 하려고 (데이터 영속성)

  • 컨테이너 사용시, 데이터 사라짐
  • 볼륨 사용시, 컨테이너가 사라져도 데이터 보존

같은 데이터를 여러 컨테이너가 쓸 수 있게

  • 볼륨 덕분에 여러 컨테이너가 같은 데이터를 함께 쓸 수 있다.
    ➡️ 데이터를 여기저기 복사할 필요 X

데이터 백업하고 옮기기 쉽게

  • 볼륨을 쓰면 데이터를 백업하거나 다른 컴퓨터로 옮기기가 편해진다.

더 빨리 돌아가게

  • 때로는 볼륨을 쓰는 게 데이터를 더 빠르게 처리할 수 있게 해준다.
  • 특히 많은 양의 데이터를 다룰 때 유용

데이터를 더 안전하게 보관하려고

  • 중요한 데이터를 컨테이너 밖에 따로 안전하게 보관할 수 있다.
    ➡️ 보안이 더 좋아짐

코드와 데이터를 따로 두려고

  • 코드를 바꿔도 데이터는 그대로 유지할 수 있다.
  • 개발이나 운영할 때 편리

Docker 공식 사이트에서는 volume ,bind mount, tmpfs mount 중에 volume을 가장 추천 !!


volume

Docker Volume을 통해 데이터를 안전하게 다룬다.
데이터를 더 잘 다루고, 여러 컨테이너에서 공유하거나, 데이터를 안전하게 관리하는데 도움된다 !!

volume : 컴퓨터에 따로 만들어진 폴더 같은 것

  • Docker가 이 폴더를 관리해서 우리가 쓰는 데이터를 여기에 저장한다.
  • 만들어 지는 곳
    - Docker는 보통 볼륨을 컴퓨터의 특정 폴더(대부분 /var/lib/docker/volumes/ 라는 곳)에 만든다.

장점

  • 백업하고 옮기기 쉽다. : 볼륨은 데이터를 다른 곳으로 옮기거나 백업하기 편하다.
  • Docker 명령어로 관리한다. : 컴퓨터에 있는 Docker 프로그램 명령어나 인터넷으로 연결된 API를 써서 볼륨을 관리
  • 어디서나 잘 돌아간다. : 리눅스나 윈도우, 어떤 컨테이너에서도 잘 작동.
  • 여러 컨테이너에서 안전하게 쓸 수 있다. : 여러 컨테이너가 같이 쓰기에도 안전하게 만들어짐
  • 볼륨 드라이버로 더 많은 기능을 추가할 수 있다. : 데이터를 다른 곳에 저장하거나 보안을 강화하는 등 여러 기능을 추가 가능.
  • Mac이나 Windows에서 더 빠르게 돌아간다. : 컴퓨터에서 Docker를 쓸 때 볼륨이 기본 저장 방식보다 훨씬 빠르게 돌아간다.

Docker Volume 실행

Docker 볼륨을 사용하여 데이터 영속성 관리

#datavol 볼륨 생성
docker volume create datavol
docker volume ls
docker container run -ti --rm -v datavol:/data alpine


# docker container 내에서
echo "볼륨 데모" > /data/demo.txt
exit

# Host Machine에서 alpine을 이용한 컨테이너 삭제 확인
docker container ls 

# 새로운 이미지와 새로운 컨테이너에서 demo.txt 파일 확인
docker container run --rm -v datavol:/data ubuntu cat /data/demo.txt

일반적으로 Docker 컨테이너는 일시적이고 휘발성인 환경이지만, 볼륨을 사용하면 컨테이너가 종료되거나 삭제되어도 데이터를 계속 유지가능 !!

  • inspect 명령으로 volume 확인
docker volume inspect datavol

암시적 볼륨 마운트

  • Docker 컨테이너가 실행될 때 자동으로 생성되는 볼륨을 말하며, 컨테이너가 종료되더라도 해당 볼륨은 삭제되지 않고 유지
docker run -d --name mysqltest -v /var/lib/mysql mysql:latest
docker inspect mysqltest # 정보가 많음
docker inspect mysqltest | jq .[].Mounts # `Name` 을 확인
docker volume ls # `Name`을 확인


mysql 데이터 보존해서 실행

Docker 볼륨을 사용하여 컨테이너 간에 데이터를 영속적으로 저장하고 공유 가능 !

  • mysql 컨테이너 실행
docker run -ti --rm -d --name mysqltest -e MYSQL_ROOT_PASSWORD=123! -e MYSQL_DATABASE=mysqltest -v ~/mysqldata:/var/lib/mysql mysql:latest

#mysql 서버에 ssh 접속 및 mysql 접속
docker exec -ti mysqltest /bin/bash
mysql -h localhost -u root -p

![](https://velog.velcdn.com/images/heejinkong/post/e106dd05-5c59-4628-8903-8316ab064a92/image.png)

- mysql 명령
```bash
show databases;

use mysqltest;
create table mysqltest(id int, name varchar(50));
insert into mysqltest values(1, 'testname');
select * from mysqltest;

#Host Machine으로 이동
exit
eixt
  • Host Machine 에서 mysqltest 디비에 데이터 확인 가능
ls -ahlvF ~/mysqldata/mysqltest

  • 동일한 데이터 사용해서 새로운 컨테이너 실행

docker stop mysqltest

docker run -ti --rm -d --name mysqltest2 -e MYSQL_ROOT_PASSWORD=123! -e MYSQL_DATABASE=mysqltest -v ~/mysqldata:/var/lib/mysql mysql:latest
docker logs -f mysqltest2
docker exec -ti mysqltest2 /bin/sh

mysql -h localhost -u root -p

use mysqltest;
select * from mysqltest;

Docker Network

Docker Network : 여러 컨테이너가 서로 통신할 수 있도록 도와주는 네트워크 시스템

  • 이를 사용하면 컨테이너 간 통신을 쉽게 설정하고, 보안을 강화할 수 있다.

개념

컨테이너 간 협력

  • 실제 비즈니스 애플리케이션을 컨테이너화할 때, 여러 개의 컨테이너가 협력하여 작업을 수행해야 한다.
  • 이때 각 컨테이너는 서로 통신을 해야만 효율적으로 작업을 할 수 있다.

네트워크 필요성

  • 컨테이너들 간에 데이터 패킷을 주고받을 수 있는 경로인 네트워크를 설정해야 한다.
  • 이를 통해 컨테이너들이 서로 연결되어 원활하게 협력할 수 있다.

Docker의 네트워크 모델 (CNM)

Docker는 컨테이너 네트워크 모델(CNM)을 제공

  • CNM: 컨테이너들 간의 네트워크를 관리하는데 필요한 기본 요건을 정의한 모델
  • 이를 통해 Docker 네트워크를 효율적으로 관리하고, 필요한 기본 요건들을 설정할 수 있다.

Docker Container Network Model

샌드박스(Sandbox)

샌드박스 : 컨테이너를 외부 세계로부터 완전히 분리시킨다.

  • 외부에서 들어오는 네트워크 연결은 샌드박스 안의 컨테이너로 들어올 수 없다.
  • 그러나 컨테이너가 외부와 전혀 소통할 수 없으면 무쓸모.
    -> 엔드포인트를 사용해서 통신을 가능하게 한다 !!

엔드포인트(Endpoint)

엔드포인트 : 외부 세계와 샌드박스(컨테이너가 아닌) 사이의 연결점.

  • 컨테이너를 안전하게 지키는 역할.
  • 샌드박스를 네트워크와 연결

네트워크(Network)

네트워크 : 엔트포인트를 통해 컨테이너 간 데이터 전달 경로.

  • 하나의 네트워크 샌드박스 안에는 여러 개의 엔드포인트가 있을 수 있다.
    - 즉, 하나의 샌드박스 안에 있는 컨테이너는 여러 네트워크에 동시에 연결될 수 있다.

네트워크 연결의 유연성

  • 컨테이너가 어디에서 작동하는지는 CNM에서 정의 X
    - 로컬 : 같은 호스트 내에서 실행될 수 있다.
    • 글로벌 : 여러 호스트에 걸쳐 실행될 수 있다.
  • CNM은 네트워크의 작동 방식을 설명하는 모델에 불과하여, 실제로 네트워크를 사용하려면 CNM을 구현해야 한다.
  • 로컬이든 글로벌이든, CNM을 구현하는 여러 방법 존재 (Docker Engine에서 구현하고 있음)

실습 - 보안 강화 가능

  • 웹 API제품 카탈로그와만 통신하고, 데이터베이스와는 통신하지 않도록 설정.
  • 제품 카탈로그두 네트워크에 연결하여 웹 API데이터베이스 모두와 통신.
  • 이렇게 하면 보안이 강화되어, 해커가 웹 API를 해킹하더라도 데이터베이스에 접근하기 어려워짐.

    여러 네트워크를 사용하여 필요한 서비스만 연결하고, 보안을 강화하는 구조 !!

# back, front 네트워크 생성
docker network create --driver=bridge back
docker network create --driver=bridge front

# 각 서비스를 생성 및 실행
docker run --name=webapi -itd --net=front ubuntu:14.04
docker run --name=catalog -itd --net=back ubuntu:14.04
docker run --name=database -itd --net=back ubuntu:14.04

# catalog 서비스는 기본 back 네트워크 뿐만 아니라 front 네트워크에도 연결
docker network connect front catalog

# webapi 의 라우팅 테이블
docker exec webapi route

# catalog 의 라우팅 테이블
docker exec catalog route

# database 의 라우팅 테이블
docker exec database route

docker network inspect front # webapi / catalog
docker network inspect back # catalog / database

docker exec -it webapi bash
# 머신 안에서
ping -c 1 catalog # 가능
ping -c 1 database # 연결 불가능
exit

# 
docker exec -it catalog bash
# 머신 안에서
ping -c 1 webapi
ping -c 1 database

# 리소스 정리
docker network disconnect front catalog

docker stop webapi catalog database

docker rm webapi catalog database

docker network rm back

docker network rm front

Docker Network 종류

브리지 네트워크

  • 기본 네트워크, 같은 컴퓨터 내 컨테이너들끼리 통신.
  • 외부 네트워크와 분리되지만, 포트 매핑으로 외부 접근 가능.

공용 네트워크

  • 외부 접근을 위해 브리지 네트워크의 포트 열기 또는 호스트 네트워크 사용.

사설 네트워크

  • 특정 컨테이너들만 통신 가능.
  • 외부와 격리되어 보안 강화.

Docker Image

Docker Image push

Docker Image를 Docker Hub Repository에 올리는 방법을 알아보자 !

push : 이미지 올리기

  • registry : Dockerfile을 통해 생성한 이미지나 docker commit을 통해 생성된 이미지를 저장하는 곳
  • Public registry : 공개적으로 사용할 수 있어 아무나 접근 가능
  • Private registry : 특정인이나 특정 그룹만 접근 가능
  • Docker Hub : hub.docker.com은 Docker 공식 Registry

Docker Hub 내 나의 계정의 Registry에 push

  • docker 계정 로그인 필수
  • Docker image tag -> push
    - 본인 계정의 repositories에 생성한 이미지를 업로드하기 위해서는, 본인 계정을 이미지명 앞에 붙여야 docker push 수행 시 계정으로 찾아가 저장 !!!
docker logout
docker login

docker image pull nginx:latest
docker image pull ubuntu:22.04

docker images

docker image tag nginx:latest kongheejin/nginx-test:1.0

생성된 이미지 Docker Hub에 올리기

docker push kongheejin/nginx-test:1.0

push 한 이미지를 웹사이트(hub.docker.com)를 통해 확인

이미지 삭제 후 내 계정의 repositoies에 있는 image pull

docker images
docker image rm kongheejin/nginx-test:1.0
docker container rm nginx-test --force
docker image rm nginx-test:1.0 --force

docker pull kongheejin/nginx-test:1.0
docker run -d -p 8001:80 --name=nginx-test kongheejin/nginx-test:1.0

curl http://localhost:8001/

  • 접속 가능

Dockerfile 최적화

왜 Dockerfile을 최적화해야 할까?

속도 향상

  • 이미지 빌드 시간을 단축시켜 더 빠르게 작업을 완료.

작은 이미지 크기

  • 저장 공간을 절약하고, 다운로드 및 전송 속도 향상.

재사용성

  • 잘 작성된 Dockerfile은 여러 번 재사용이 가능해 효율적

보안 강화

  • 보안 취약점을 줄여 해킹 위험을 낮출수 있음.

유지보수 용이

  • 깔끔하게 정리된 Dockerfile은 향후 수정과 업데이트가 쉬움.

Java 환경 Docker 이미지 빌드

  • alpine 이미지를 사용해서 최소한의 라이브러리만 설치된 이미지를 사용하여 빌드
  • multi stage를 사용하여 application 실행 Container에 gradle이 설치되는 것을 방지
#Dockerfile

# 1. 빌드 단계
# build 는 gradle 이미지에서 `builder`라는 이름으로.
FROM gradle:8.5-jdk21-alpine AS builder

WORKDIR /app
COPY ./ ./
RUN gradle clean bootJar


# 2. 애플리케이션 실행 단계
FROM eclipse-temurin:21-jre-alpine

WORKDIR /app
COPY --from=builder /app/build/libs/spring-boot-0.0.1-SNAPSHOT.jar .

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "spring-boot-0.0.1-SNAPSHOT.jar"]
  • 멀티 스테이지 빌드를 사용하여 효율적인 이미지 빌드를 구현
  • 두 개의 이미지를 사용해 애플리케이션을 빌드하고 실행하는 단계가 나눠져 있어, 최종 이미지가 더 경량화된다.
profile
🔥💻🔥

0개의 댓글