일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- nvl2
- 데이터 프로젝트
- 비지도학습
- ifnull
- 데이터 전처리
- SQL
- 정밀도
- layer normalization
- 백엔드
- 평가 지표
- 강화학습
- 웹서비스 기획
- DecisionTree
- 빠르게 실패하기
- sorted
- 오차 행렬
- Normalization
- five lines challenge
- beautifulsoup
- 감정은 습관이다
- 재현율
- recall
- CASE WHEN
- 지도학습
- NULLIF
- NVL
- LAG
- Batch Normalization
- 데이터 분석
- 결정트리
- Today
- Total
Day to_day
Docker 최소한의 개념과 기본 사용법 알아보기 본문
❗본 포스팅은 Maximilian Schwarzmüller의 'Docker & Kubernetes : 실전 가이드' 강의 기반으로 개인적인 정리 목적 하에 재구성하여 작성된 글입니다.
Docker
도커를 한마디로 하면 컨테이너 기술이다. 컨테이너를 생성하고 관리하기 위한 도구이다.
그러면 컨테이너는 무엇인가. 표준화된 소프트웨어 유닛이라고 할 수 있다. 이는 기본적으로 코드 패키지이며 해당 코드를 실행하는데 필요한 종속성과 도구를 포함시킬 수 있다.
예를 들어 NodeJS로 앱을 만든다고 하면 컨테이너에는 해당 애플리케이션의 소스 코드뿐 아니라 NodeJS 런타임, 코드를 실행하기 위한 기타 도구들이 있을 것이다. 그것들을 하나의 컨테이너로 만들게 되면 항상 동일한 버전을 사용하여 동일한 결과를 얻을 수 있다는 이점이 있다.
그러니 컨테이너 단위로 프로젝트를 만들게 되면 여러 사람과 공유해도 모두 같은 환경을 구성할 수 있고 같은 결과를 얻을 수 있게 된다.
도커는 알면 알 수록 활용할 수 있는 기능들이 많이 있지만 그것에 관해서는 차차 배워가기로 하고 이번 포스팅에서는 기본적으로 사용하는 방법에 대해서 적어보려 한다.
Docker Architecture
Docker는 기본적으로 클라이언트-서버 아키텍처를 사용한다.
도커 클라이언트는 도커 컨테이너를 빌드, 실행 및 배포하는 무거운 작업을 수행하는 도커 데몬과 통신하고,
둘은 동일한 시스템에서 실행할 수도 있고, Docker 클라이언트를 원격 Docker 데몬에 연결할 수도 있다. Docker 클라이언트와 데몬은 REST API, UNIX 소켓 또는 네트워크 인터페이스를 통해 통신한다.
또 다른 Docker 클라이언트로는 컨테이너 집합으로 구성된 애플리케이션으로 작업할 수 있는 Docker Compose가 있다.
도커를 처음 사용해 보는 입장에서는 사실 위의 내용이 지금 모두 이해가 안 돼도 괜찮다.
일단 이런 아키텍처로 동작하는구나 정도 알고 사용해 보면서 이해해도 좋을 것 같다.
도커 데몬 (Docker daemon)
- 도커 엔진 핵심 구성 요소
- 도커 호스트에서 컨테이너 관리 및 실행
- 컨테이너 생성, 시작, 중지, 삭제 등 작업 수행
- 컨테이너 이미지 관리
도커 클라이언트 (Docker CLI)
- Docker daemon을 제어하는 것
- Docker 명령어를 사용하여 Docker daemon으로 보내어 실행
도커 레지스트리
- 도커 이미지 관리 및 저장
- Docker hub: 디폴트 레지스트리, 누구나 접근 가능한 공개형 저장소
도커 오브젝트
- 도커 이미지
- 도커 컨테이너를 만들기 위한 읽기 전용 템플릿
- 도커 컨테이너
- 한 도커 이미지의 실행 가능한 인스턴스
- 애플리케이션 실행하기 위한 모든 파일과 설정 정보 포함 패키지
그래서 어떻게 도커를 사용해 볼까?
기본적으로 도커는 이미지를 만들어야 컨테이너로 사용이 가능하다.
도커 이미지는 비유하자면 도면이라고 할 수 있다. 도면을 먼저 만들고 그 도면대로 컨테이너를 만드는 것이다.
도커 이미지는 특징이 하나 있는데 Docker 컨테이너를 만들기 위한 지침이 포함된 “읽기 전용 템플릿”이라는 점이다. 그래서 이미지를 수정하고 싶다면 해당 이미지가 업데이트되는 게 아닌 새로운 이미지를 만들고 또 다시 그 이미지를 빌드해야 컨테이너에 적용된다.
그러면 그 이미지를 만들기 위해서는 2가지 방법이 있다.
- 직접 Dockerfile을 만들어서 docker build로 이미지를 만들어주기
- Docker hub에서 특정 도커 파일을 pull(docker pull)해서 이미지로 만들어주기
그렇게 이미지가 만들어지면 하나의 도커 이미지로 컨테이너 여러 개를 띄워 각각 같은 조건의 컨테이너들을 만들 수 있다.
도커 자체 파일 구조 (Dockerfile)
도커 이미지를 만들기 위해서 간단하게 Docker hub에서 pull 해오는 방법은 쉬우니 검색하면 금방 나올 것이다.
그래서 여기서는 어떻게 Docker file을 구성하고 빌드하는 방법을 알아보겠다.
도커 이미지는 여러 겹의 레이어로 구성이 되어있고, 레이어 순서대로 빌드가 된다. 이 레이어라는 개념을 알고 가야 하는 이유는 만약 도커 이미지를 수정하여 re-build 하고 싶을 때 변경된 부분의 명령과 그 이후의 모든 명령이 재평가되기 때문이다. 쉽게 말해 도커는 캐시(cache)를 이용하기 때문에 이미지를 다시 빌드할 때는 변경된 부분 이전은 저장된 캐시를 이용하고 그 이후부터 다시 빌드를 해야 한다.
Dockerfile 구성 요소
- FROM
- 베이스 이미지 선정
- 반드시 있어야 하는 명령어
- 여러 겹의 이미지를 쌓아가는데, 그 층 중 가장 기본이 되는 이미지
- WORKDIR
- 도커 파일 뒤에 오는 모든 지시자 (RUN, CMD, COPY, ADD)에 대한 작업 디렉터리 설정
- 리눅스 명령어의 cd와 비슷한 역할
- COPY
- 복사할 파일 선정 (작업한 서비스 파일들)
- 현재 로컬 컴퓨터에 있는 파일을 도커 컨테이너 안으로 복사하는 기능
- RUN
- 이미지 빌드 시 실행할 명령어
- CMD
- RUN 명령어가 이미지 빌드할 때 실행되는 것과 달리 CMD는 이미지로부터 컨테이너를 생성할 때 최초로 수행됨
- CMD의 경우 배열로 문자열로 구성해야 함
자체 이미지 파일 생성하기
Dockerfile 생성 예시
FROM python
WORKDIR /main
COPY . ./ # Dockerfile과 같은 path에 있는 모든 파일을 현재 디렉토리로 카피
# COPY . /main # 근데 이런식으로 절대 경로로 넣어줘도 괜찮! (앞에 ./를 붙이지 않는 것만 주의)
RUN pip install -r requirements.txt
# RUN python test.py # 이건 틀린 예시! 이렇게 하면 컨테이너가 시작할때마다 이 파일이 시작되는 것임
# 대신에 CMD를 사용해준다
CMD ["python", "test.py"]
FROM: 운영체제를 넣어줘야 한다. 예를 들어 ubuntu, node가 있다. 이때 docker hub에 나와있는 이름으로 써야 하고, 로컬 머신에 없는 경우 자동으로 hub에서 pull 해서 로컬 머신에 설치한다.
WORKDIR: 폴더를 지정해서 RUN에 해당하는 커멘드를 실행시킬 path를 정해주는 것이다. RUN에 해당하는 코드를 바로 실행하도록 할 건데 여기서 WORKDIR를 추가하지 않으면 도커 루트에서 실행되어 버린다.
여기서 잠깐! FROM 다음 WORKDIR를 실행하기 때문에 기본 디렉터리를 /main으로 설정했기 때문에 COPY에서 또 /main을 정해줄 필요가 없다.
COPY: 어떤 파일에 Dockerfile이 들어가야 되는지 알려주는 것이다.
첫번째 . 은 현재 Dockerfile이 위치한 이 프로젝트의 모든 폴더, 하위 폴더 및 파일을 모두 카피하라는 의미 (Host file system)
그래서 Dockerfile이 작업하길 원하는 폴더 안에 들어가 있거나 하면 안 된다.
두번째 . 은 그래서 카피한 모든 파일을 도커 내부 이미지의 어떤 경로에 저장할 것인지 정하는 것이다. (Image/container file system)
보통 도커 컨테이너의 root 엔트리를 사용하지 않고 사용자가 선택한 서브 폴더를 사용하는 것이 좋다. (지금 예시의 경우는 WORKDIR를 /main으로 설정해 줬기 때문에 'COPY . ./'을 하면 도커 컨테이너의 /main 경로에서 카피한 소스 코드들이 들어갈 것이다.)
CMD: 이미지가 생성될 때 실행되지 않고, 이미지를 기반으로 컨테이너가 시작될 때 실행되는 것
그런데 CMD는 배열로 값이 들어간다. 그래서 python test.py를 실행시키고 싶다면,
CMD [”python”, “test.py”] 이렇게 적어줘야 한다.
EXPOSE: 컨테이너는 로컬 머신과 분리되어 있기 때문에 만약 로컬 서버와 도커 내 컨테이너가 통신을 하고 싶다면 포트 번호를 노출시켜 주어야 찾을 수 있다. 다음과 같이 포트번호를 넣어서 사용할 수 있다. EXPOSE 80
도커 이미지 빌드하기
docker build .
이제 docker build를 통해 자체 Dockerfile을 이용해 이미지를 생성한다. 명령어 마지막에 . 을 찍어주면서 동일한 폴더에 Dockerfile이 존재함을 알려준다.
Docker Container lifecycle
Docker 컨테이너의 lifecycle로 컨테이너의 상태가 변화하는 과정과 명령어를 정리해 봤다.
- Created (생성됨) 상태:
- 컨테이너가 생성되었지만 아직 실행되지 않은 상태이다.
- 이미지에서 create 명령어를 사용하여 컨테이너를 생성할 수 있다.
- 그리고 이미지에서 run 명령어를 사용하면 컨테이너가 생성되고 바로 Running 상태로 넘어간다.
- Running (실행 중) 상태:
- 컨테이너가 현재 실행 중인 상태이다.
- start 명령어로 컨테이너를 Created 상태에서 Running 상태로 전환할 수 있다.
- pause 명령어로 컨테이너를 일시 정지하여 Paused 상태로 만들거나 stop 명령어로 컨테이너를 Stopped 상태로 전환할 수 있다.
- 주로 컨테이너를 stop 시키기 위해서는 stop 명령어를 통해 종료시키지만 긴급하거나 강제로 종료시켜야 하는 경우 kill 명령어로 강제로 컨테이너를 종료시킬 수 있다.
- Paused (일시 정지됨) 상태:
- 컨테이너가 일시 정지된 상태로, 프로세스는 멈춰 있지만, 실행 상태는 유지되는 상태다.
- unpause 명령어를 사용하면 다시 Running 상태로 돌아갈 수 있다.
- Stopped (중지됨) 상태:
- 컨테이너가 중지된 상태에서 start 명령어로 다시 Running 상태로 전환할 수 있다.
- 그리고 Running 상태인 컨테이너를 삭제하진 못하고 반드시 중지된 상태에서 rm 명령어를 사용하여 컨테이너를 삭제하여 Deleted 상태로 만들 수 있다.
- Deleted (삭제됨) 상태:
- 컨테이너가 삭제된 상태로 더 이상 사용할 수 없다.
이와 같이 Docker 컨테이너는 다양한 상태를 거치며 실행되고 관리된다. 상태 간의 전환은 특정 명령어를 사용해 이루어지며, 이를 통해 컨테이너의 라이프사이클을 관리할 수 있다.