[학습] 도커를 학습해보자!!

반응형
반응형

설계에 대한 학습은 어느정도 되있는 상태인데..
개발에 대한 마지막이라고 할수 있는 CI/CD에 대한 지식이 너무 전무하다는 생각이 들었다.
이 글은 도커에 대한 전반적인 내용은 다루지 않을 예정이다.
내가 이해하고 학습한 내용을 작성할예정이다.
이렇게 하는이유는 이론적으로 학습한다고 해서 이걸 기억하기에는 쉽지 않을거고
도커에 대한 모든 내용을 내가 사용하지 않을 가능성도 높다.
그렇기 때문에 도커가 왜 필요하고 어떻게 사용하는등 언제든지 사용할 수 있는 범위해서 공부할 예정이다.
그래야 퍼즐처럼 끼워맞추기가 가능할거구 확장을 한다면 조금더 편할거라 생각한다.

그러면 내가 왜 CI/CD를 학습하면서 왜 도커를 먼저 학습을 할려고 하는지 이해를 해야한다.
그래야 도커와 CI/CD의 연관성을 생각하면서 공부할 수 있기 때문이다.
엄밀히 말하면 도커와 CI/CD는 함께 설명되어지는 용어는 아니라고 생각한다.
도커따로 CI/CD따로 공부해도 이상하지는 않는다.
하지만, 도커와 CI/CD를 함께 공부를 해야 하는 이유를 생각해보자.
도커는 컨테이너다. 그러니까 개발할, 개발된 프로젝트 혹은 프로그램을 컨테이너로 묶고 이것을 배포한다고 생각해보자.
그러면 조금더 관리가 편할거라는 추상적인 생각이 든다.
암튼, 도커는 일단 컨테이너라고 생각하는데 실상은 뭐 아닐 수 있긴한데 나한테 이미지는 현재 컨테이너라고 생각한다.
그러면 진실은 과연 무엇일까?
AI를 돌려보니 다음과 같은 답변을 들을 수 있었다.

아니요, 도커(Docker)는 컨테이너 자체가 아니라 컨테이너를 생성하고 관리하는 플랫폼입니다. 좀 더 자세히 설명드리겠습니다:

도커는 컨테이너화 기술을 구현하고 쉽게 사용할 수 있게 해주는 소프트웨어 도구입니다.
컨테이너는 도커를 통해 생성되는 격리된 애플리케이션 실행 환경입니다. 이는 애플리케이션과 그 종속성을 패키징하여 어디서나 일관되게 실행할 수 있게 해줍니다.
도커는 다음과 같은 주요 기능을 제공합니다:

컨테이너 생성
컨테이너 관리
이미지 빌드
컨테이너 간 네트워킹
리소스 관리


컨테이너는 도커의 결과물이며, 도커 엔진을 통해 만들어지고 실행됩니다.

쉽게 비유하자면, 도커는 컨테이너를 만드는 공장이고 컨테이너는 그 공장에서 생산된 제품이라고 할 수 있습니다.

그러니까 도커는 컨테이너라는걸 생산하고 관리하는 플랫폼이라고 한다.
결국 내가 생각한 도커 == 컨테이너라는 말은 틀린걸까? 이렇게 이해하면 안되는 걸까?
안된다고 한다. 위에서 읽어보니 도커는 컨테이너를 만드는 공장이라는데.. 뭔지는 모르겠지만 도커를 통해 컨테이너라는 걸 생산할 수 있는거 같다.
그러면 컨테이너라는건 무엇일까?
아니 질문을 바꿔서 컨테이너안에는 무엇이 존재할까? 내가 생각할때 도커는 컨테이너를 운반하는 역할을 담당하는 거 같다.
결국 컨테이너라는건 그리 중요하지 않고 컨테이너안에 무엇이 담기는지 부터 생각을 해야 한다.

컨테이너에는 이미지가 담겨진다. 그렇다면 아까 내가 도커는 컨테이너라고 했었던것이 어느정도 일리가 있는 생각인듯 싶다.(결론적으로 틀렸지만..)
암튼 도커는 어떻게 이미지를 만드는 걸까?

찾아보니 가상화라는걸 사용해서 리소스를 추상화한다고 한다.
결국 내가 알아야하는건 어떻게 리소스를 추상화를 시킬 수 있을지를 생각해봐야 한다.
이것도 AI를 돌리니 다음과 같은 답변을 들을 수 있었다.

네트워크 추상화

도커 네트워크 드라이버를 통해 컨테이너 간 통신을 추상화
bridge, host, overlay, macvlan 등 다양한 네트워크 모드 제공
컨테이너에 가상 IP 주소 할당
포트 매핑을 통해 호스트와 컨테이너 간 네트워크 연결 관리


스토리지 추상화

볼륨(Volumes)을 통해 컨테이너 데이터 지속성 관리
바인드 마운트와 tmpfs 마운트 등 다양한 마운트 방식 제공
스토리지 드라이버를 통해 다양한 파일 시스템 지원
데이터 영구 보존 및 컨테이너 간 데이터 공유 용이


컴퓨팅 리소스 추상화

CPU와 메모리 제한 설정 기능
cgroups를 활용한 리소스 할당 및 격리
--cpus, --memory 등의 옵션으로 컨테이너별 리소스 할당 제어
오버커밋(Overcommit) 방지 및 리소스 공정 분배


프로세스 격리

네임스페이스를 통한 프로세스 격리
각 컨테이너는 독립된 프로세스 공간 보장
루트 디렉토리, 네트워크 인터페이스, 프로세스 트리 등 격리


이미지 레이어 추상화

이미지를 여러 레이어로 분리
중복 레이어 공유를 통한 저장공간 및 다운로드 효율성 개선
레이어 캐싱으로 빌드 및 배포 속도 최적화


런타임 환경 추상화

개발, 테스트, 운영 환경의 일관성 유지
종속성과 실행 환경을 이미지로 캡슐화
환경 변수를 통한 설정 관리

이 모든걸 학습하면 좋겠지만 너무 광범위한거 같다. 그러면 나는 두가지 시나리오를 통해 학습을 할 수 가 있다.

1. 특정 기술을 도커로 사용 할때
2. 스프링 프로젝트를 도커로 관리할때

이거 보다 다양한 시나리오가 있겠지만 내가 학습을 해야 하는 범위는 요정도면 충분할거 같다.
첫번째 같은 경우는 그냥 인터넷 보고 사용하면 되는데 두번째 경우같은 경우는 상황이 달라진다.
왜냐하면 이미지를 다운을 받는거와 이미지로 만들어서 사용하는건 다른 상황이기 때문이다.
일단 이미지로 만들기 위해서는 도커가 이해할 수 있는 언어로 바꿔줘야 한다.
도커라는게 쉽게 생각해서 배포라고 생각하면된다. 그러니까 우리가 개발하고 있는 환경이 아니라 인프라 환경이라고 생각하면 쉽다.
그러니까 도커로 이미지를 만드는 행위가 인프라 환경에 배포하는 행위와 굉장히 유사하다.
예를들어

FROM eclipse-temurin:17-jdk-jammy

WORKDIR /app

# 빌드된 jar 파일 복사
COPY build/libs/*.jar app.jar

EXPOSE 8088

ENTRYPOINT ["java", "-jar", "app.jar"]

이와같은 도커파일을 만들었다고 생각해보자. 그러면 8088포트로 이미지가 만들어진다. 그러면 도메인은 어떻게 작성을 해야 할까?
아까 말했듯이 도커로 이미지를 만들어서 관리한다는건 인프라 환경에 배포한다는거와 비슷하다. 그러니까 도메인은 localhost가 아니라는 점이다. 당연히 환경이 달라졌는데 localhost로 동작하는게 이상하다고 생각이 든다.
그런데 왜 도커는 localhost로 생각하는 걸까? 그건 생각보다 간단하다. 그건 도커로 이미지를 다운을 받게 되면 localhost로 사용할 수 있게 해주기때문이다. 그래서 간과한것인데 사실은 또 다른 환경이기때문에 다른 도메인을 사용하는 것이 맞다.
근데 왜 도커로 이미지로 사용하는건 왜 localhost냐고?? 도커에서 뭔 조작을 해주지 않을까? 잘 모르겠다. 중요한건 요게 아니기 때문에 넘어갈거 같다. 하지만 나중에 찾아보면 좋지 않을까 싶다.
그러면 도커로 만든건 도메인을 어떤식으로 가져가야 할까? host.docker.internal 요걸 도메인에 적게 되면 도커환경에서 접근을 할 수있게 해준다. 이렇게 하면 서로 다른 도커 환경에서 접근이 가능하게 되어진다. (이거는 서로 다른 도커 컨테이너에 접근하는 경우고 직접 프로그램을 다운받아서 하는경우 직접 IP를 주소를 적어야 하는 걸까? 요거는 모르겠다.ㅎㅎ; 아무렴어때 요즘은 도커로 모든걸 다운 받는데..)
근데 이와 같은 상황은 네트워크가 다른 경우고 이걸 도커내에서 같은 네트워크를 사용하게 한다면?
당연히 localhost로 사용할 수 있지 않을까 그러면 우리가 생각을 해야 하는것이 어떻게 하면 같은 네트워크를 사용하게 하는것인지 고민을 해봐야 한다. 그렇다면 어떻게 같은 네트워크를 구성할 수 있을까? 고걸 한번 찾아보자.

도커 네트워크는 컨테이너 간 통신과 외부 연결을 관리하는 중요한 기능입니다. 주요 네트워크 모드와 사용 방법을 간략히 설명드리겠습니다:

기본 네트워크 모드


Bridge (기본값)
컨테이너가 격리된 가상 네트워크에서 통신
호스트와 컨테이너 간 포트 매핑 가능

# 특정 포트 매핑 예시
docker run -p 8080:80 nginx

Host 네트워크 모드


호스트의 네트워크 인터페이스 직접 사용
네트워크 격리 없음

docker run --network host nginx



Custom 네트워크 생성


사용자 정의 브릿지 네트워크 생성
컨테이너 간 격리된 통신 가능

# 네트워크 생성
docker network create mynetwork


# 네트워크에 컨테이너 연결
docker run --network mynetwork nginx

컨테이너 간 통신


사용자 정의 네트워크에서 컨테이너명으로 통신 가능

# 컨테이너 간 통신 예시
docker network create myapp
docker run --name web --network myapp nginx
docker run --name db --network myapp mysql

네트워크 관리 명령어

# 네트워크 목록 확인
docker network ls

# 네트워크 상세 정보
docker network inspect bridge
주요 장점:

유연한 네트워크 구성
컨테이너 격리
쉬운 포트 매핑
사용자 정의 네트워크 생성 가능

요런식으로 생각할 수 있다고 한다. 물론 도커가 IP어떤식으로 할당하는지에 대해서는 잘모르겠다.

# mynetwork라는 네트워크 생성
docker network create mynetwork

# web 컨테이너 생성
docker run --name web --network mynetwork nginx

# db 컨테이너 생성
docker run --name db --network mynetwork mysql

이런식으로 작성하게 되면 network라는 대역에서 nginx와 mysql을 사용할 수 있게 된다.
그러면 다시 돌아와서 얘네를 같은 네트워크로 배포를 한다고 가정하자.
그러면 실제 로컬에서는 쟤네를 어떻게 사용할 수 있을까?
그냥 도메인을 localhost로 지정하면 된다고 한다. 결국 도커에서 network를 작성하는 이유는 도커 이미지 혹은 컨테이너가 서로 통신하기 위함으로 이해하면 될거 같다.

마지막으로 볼륨이라는것이 있다. 볼륨은 간단히 말해서 저장공간으로 알고 있다. 그렇다는건 도커 환경에 저장공간을 만들어서 관리를 하는것이 아닐까싶다.

docker run -v myvolume:/data/myapp myimage

요런식으로 만들게 되는데 

볼륨을 사용하는 대표적인 경우들은 다음과 같습니다:

데이터베이스 데이터 보존


MySQL, PostgreSQL 등 데이터베이스 컨테이너의 데이터 영구 저장
컨테이너 재시작이나 삭제해도 데이터 유지


파일 업로드 및 사용자 컨텐츠 관리


웹 애플리케이션의 사용자 업로드 파일 저장
이미지, 동영상 등 정적 파일 관리


로그 파일 관리


애플리케이션 로그 영구 보존
로그 분석 및 모니터링을 위한 데이터 유지


개발 환경 설정


소스코드, 의존성 라이브러리 캐시
개발 환경의 설정 파일 지속적 관리


백업 및 복원


중요 데이터의 주기적 백업
다른 환경으로 데이터 마이그레이션

같은 경우에 사용이 되어진다고 한다.
근데 솔직히 얘는 관리 목적이지 사용목적으로는 몰라도 크게 문제되지 않을거 같다. 다만 운영측면에서 중요 데이터를 저장해야 하는 상황이라면 이러한 방법을 선택하는 것도 방법일거 같다.

다음은 도커파일과 도커-컴포즈에 대해 학습하려고 한다. 얘네는 그리 길지 않을거 같아 글 하나로 퉁칠생각이고
이 글이 도커의 전부라고 생각하면 안된다. 이 글은 어디까지나 언제든지 도커를 사용할 수 있게 작성했을뿐이지 도커에 대한 심도깊은 이해를 적은것이 아니기때문에 이를 참고했으면좋겠다. 또, 틀린 내용이 있을 수도 있다. 

반응형

댓글

Designed by JB FACTORY