Docker 정리

yjbenkang·2024년 11월 18일

Airflow 운영상의 어려움 (다수의 소프트웨어에도 적용됨)

관리해야하는 DAG의 수가 100개를 넘어간다면 ?

  • 데이터 품질이나 데이터 리니지 이슈 이외에도 다양한 이슈들이 발생
  • 어떤 이슈들이 있을까?
    • 라이브러리 충돌
    • Worker의 부족 : 처음엔 싱글노드로 돌아서 서버 하나로 돌리는데, 많아지면 하나론 부족. Multi node cluster로 바뀌어야함. 다수의 서버를 airflow cluster에 할당할 경우, 놀고 있는 서버로 인한 자원 낭비, 각 기술마다 서버를 별도로 구성하면 관리가 어려워짐. CPU, 디스크, 메모리가 놀고 있는 경우가 많아지게 됨.
    • Worker 서버들의 관리와 활용도 이슈

1. 라이브러리 충돌

  • 라이브러리/모듈의 충돌 이슈가 발생하기 시작함
  • DAG에 따라 실행에 필요한 라이브러리/모듈이 달라지기 시작
    • 예) Python 버전
  • 이로 인해 DAG 혹은 Task별로 별도의 독립공간을 만들어주는 것이 필요
    • Docker to the rescue
    • Dag 혹은 Task 코드를 Docker Image로 만들고 이를 독립된 공간(Docker Container)안에서 실행

2. Worker의 부족

  • Scale Up : 서버 사양 올리는 것, 어느 시점 한계에 도달
  • Scale Out : 워커 노드를 계속 증가. 클라우드 기반의 airflow 서비스 사용 고려
    • 클라우드 서비스 사용
  • k8s와 같은 컨테이너 기술 사용
    • 필요한대로 서버 요청

3. 낮은 Server Utilization Issue

  • Airflow 전용 하드웨어를 지정했는데 서버들이 항상 바쁘지 않다면 ?
  • 서비스별로 전용 서버를 할당하는 것은 여러가지로 이슈를 만들어냄
    • 서비스별로 Capacity 관리를 해야함
    • 각 서비스에 속한 서버들은 보면 utilization이 낮은 이슈 발생
  • 이 역시 k8s와 같은 컨테이너 기술의 도입으로 해결 가능

해결책

  • 태스크나 DAG 코드를 Docker Image로 만들어서 Docker Container 형태로 실행
    • 라이브러리/모듈 충돌을 방지
    • 개발 환경과 프로덕션 환경을 동일하게 유지
  • Airflow Worker를 K8S에서 필요한 대로 동적으로 할당하여 사용
    • 전용 서버를 Airflow에 할당하지 않고 Container Orchestration 서비스를 통해 할당해서 사용하고 리턴
  • Airflow에서 이를 해결하는 방법은 3가지
    a. Airflow Operator로 KubernetesPodOperator를 사용
    b. Airflow Operator로 DockerOperator를 사용
    c. Airflow Executor로 아래를 사용
    • KubernetesExecutor
    • CeleryKubernetesExecutor
    • LocalKubernetesExecutor

Airflow Executor란

  • Executor는 Task들을 관리하고 실행하는 역할을 수행
    • 병렬 혹은 일렬 실행이나 어느 worker에서 실행할지 등등
  • 다양한 수의 Executor 타입이 존재
    • Sequential Executor: 디폴트로 설치되며 sqlite와 같은 싱글스레드 DB에서만 사용 가능
    • Local Executor: task들을 Airflow 마스터 노드안에서 실행
    • Celery Executor: 다수의 Worker 노드가 있는 경우 사용되며 Celery 큐를 사용해 task들을 worker 노드로 분산하여 실행
    • Kubernetes Executor는 k8s 클러스터를 사용하여 task들을 독립된 환경에서 사용
    • Local Kubernetes Executor와 Celery Kubernetes Executor도 존재

Airflow 아키텍처: Docker와 k8s을 사용하는 방법

  • Airflow Operator로 KubernetesPodOperator를 사용
    • 이 방식은 특정 태스크를 Docker Image로 만들어 k8s에서 실행
  • Airflow Operator로 DockerOperator를 사용
    • 이 방식은 특정 태스크를 Docker Image로 만들어 Docker Container 위에서 실행
  • Airflow Executor로 다음 중의 하나를 사용
    • KubernetesExecutor
      • 모든 DAG 코드가 Docker Image로 빌드되어 k8s에서 실행됨
    • CeleryKubernetesExecutor
      • CeleryExecutor와 KubernetesExecutor를 동시에 사용하는 방법을 제공해주는 Executor
      • 이는 Airflow 로드가 전체적으로 큰데 소수의 task만 Isolation을 필요로 하는 경우
    • LocalKubernetesExecutor
      • LocalExecutor와 KubernetesExecutor를 동시에 사용하는 방법을 제공해주는 Executor

Docker란?

Docker가 가장 필요한 이유는 내가 만든 프로그램이 내 컴퓨터 내 개발환경에서는 잘돌아가는데 다른사람이 가져가 쓰는 순간 혹은 테스트 프로덕션 환경에서 안돌아가는 경우.(이런경우가 꽤 많음)

  • 라이브러리 혹은 모듈의 충돌이 가장 큰 이유
    • 가장 골치 아픈 문제
  • 설치 과정에서 중요한 파일이 빠짐
  • 환경 설정이 안 맞는 것이 존재

그중에 가장 효율적이고 많이 사용되는 솔루션이 Docker

내 컴퓨터 환경을 그대로 패키징해서 다른 이에게 줄 수 있다면 ?

  • Docker Image : 이렇게 독립적으로 완전하게 만들어진 패키지,내가 만든 소프트웨어를 완전한 형태로 모든 디펜던시가 있는 라이브러리를 포함해서 패키징. 이걸 만드는걸 build한다고 한다.
  • Docker Container : 이 Docker Image를 독립된 환경에서 실행한 것. os와 다른 컨테이너와 별도로 docker engine위에서 돈다 (host 컴퓨터 위가 아닌). host os와 다른 컨테이너와 충돌이 생기지 않게 보장. VM과 비슷하지만 훨씬 light-weight. VM은 이자체에 OS를 가지므로 헤비하고 속도도 느리지만 컨테이너는 docker container가 다수로 돌 수 있는 세팅.

개발에 사용했던 컴퓨터 환경을 그대로 패키징해서 다른사람에게 줄 수 있다면 다른사람도 내가 개발한 것처럼 사용할 수 있다.

docker-compose란 다수의 컨테이너로 구성된 애플리케이션이 있을 때 사용되는 명령어.

Docker의 목표

  • 소프트웨어를 일관되게 빌드하고 실행하고 배포
    Docker File -Build-> Docker Image -Run-> Docker Container

Virtual Machines vs Docker Containers

Virtual Machine 소개

  • AWS의 EC2가 대표적인 Virtual Machine (VM)
  • 하드웨어를 추상화하여 한 컴퓨터 위에 가상 컴퓨터를 올리는 것
    • 즉 컴퓨터 하드웨어 단의 추상화

      Virtual Machines: 보통 하나의 컴퓨터 위에 다수의 VM을 실행하는 것이 일반적. 이 안에서 소프트웨어가 동작
      VM을 생성하고 관리하기 위한 소프트웨어 : VMWare, VirtualBox, Hyper-v, ...
      Hypervisors: VM을 생성하고 관리하는 레이어
      하드웨어 안에 또다른 하드웨어가 돌아가는 꼴

Virtual Machine의 장단점

  • 장점
    • 소프트웨어를 실행하기 위한 독립적이고 분리된 공간을 제공. 소프트웨어 호환성에 있어서 진짜 컴퓨터 쓰는 느낌.
    • 다수의 소프트웨어를 각 VM단에서 독립적으로 실행가능(하드웨어간의 충돌이슈 사라짐)
  • 단점
    • 각 VM은 자신만의 OS를 필요로 함 (가상 하드웨어 위에서 돌기 때문)
      • 유료 OS(Windows, Redhat 등)라면 라이센스 비용 필요
      • 그러다보니 시작하는데 오래 걸림
    • 자원을 많이 사용함 (VM들끼리 자원을 나눠써야함), 메모리도 더 쓰고 디스크도 더 쓰고
      • 다수의 VM을 올리면 문제가 더 커짐

Docker Container

  • 소프트웨어를 실행하기 위한 독립적이고 분리된 공간

  • 자체 파일 시스템을 갖고 있음 (Volume이라고 부름)

  • 지원하는 컨테이너 OS

    • 맥 : 경량화된 리눅스 VM이 동작함
    • 윈도우 : 윈도우, 리눅스
    • 리눅스 : 리눅스

      많은 기능을 docker engine에 의존하는 형태
      Docker Engine이 그냥 애플리케이션이 아니라 리눅스가 돌아가는 VM
      Docker로 만드는 소프트웨어는 리눅스인경우 어디서든 돌아감
      윈도우 애플리케이션이면 윈도우에서만 돌아감.
      또하나의 단점은 커맨드라인 어플리케이션 만들기엔 좋은데, window나 맥엔토시만들기엔 제약적
  • 장점

    • 소프트웨어를 실행하기 위한 독립적이고 분리된 공간을 제공
      • 다수의 소프트웨어를 각 컨테이너단에서 독립적으로 실행가능
    • 자원 소비가 적음 (lightweight)
      • 한 호스트에서 몇 십개에서 몇 백개의 container를 실행 가능
    • 호스트 OS를 사용 (별도 비용 없음)
      • 따라서 빠르게 실행됨
  • 단점

    • 많은 수의 Docker Container를 관리하는 것은 쉽지 않음
    • Host OS를 사용하기에 Cross-platform compatibility를 항상 지원하지 않음
    • GUI 소프트웨어 개발에 적합치 않음

Docker 프로그램 개발 프로세스

Docker로 소프트웨어를 패키징(빌드)하는 프로세스

하이레벨 Docker 사용 프로세스

먼저 대상 소프트웨어를 선택

  • 다수의 컴포넌트로 구성되는 소프트웨어라면 각각이 Docker Image로 만들어져야할 수도 있음
  • 이를 Docker Image로 빌드하자: Dockerization이라고 부른다.
    - Dockerfile이란 텍스트 파일로 세부 정보를 기술
    - 해당 소프트웨어를 이미지로 바꾸기 위한 Docker에게 주는 명령들을 포함
    - Docker Image : 하나의 Docker Container안에서 실행됨
    - Dockerfile을 기준으로 만들어지며 소프트웨어를 실행하기 위해 필요한 모든 것을 포함

Docker Image의 구성 요소

  • 기본 OS (리눅스라면 우분트, 데비안 등등)와 같은 소프트웨어의 실행환경
  • 소프트웨어 자체 (코드)
  • 소프트웨어가 필요로 하는 라이브러리
  • 파일 시스템 스냅샷: 이는 스택화된 형태로 구현됨 (뒤에서 더 설명)
  • 환경 설정 변수: 빌드할 때 변수와 실행 때 변수 두가지가 존재 => ENV, ARG
  • 메타 데이터: 이미지 자체에 대한 정보 (버전(안붙이면 latest), 작성자, 설명 등등)

위 정보와 설치 관련 실행 순서들이 Dockerfile에 기술됨
Docker Image는 다수의 파일로 구성됨 ("docker image ls")

Docker Image의 실행

  • Container를 통해 Docker Image안의 소프트웨어를 실행
    • Container는 자체 파일 시스템을 가진 특수한 프로세스로 이미지의 파일 시스템이 로딩됨
  • Image를 Container 안에서 실행
    • docker run ...

Docker Image의 등록 : Docker Hub

  • Docker Registry는 Docker Image들의 보관소
    • On-prem registry(회사내에서만 사용,private)와 Cloud registry(public or private)가 존재
    • docker hub가 가장 유명하다.
  • 여기에 등록을 하면 회사내 혹은 퍼블릭하게 이미지를 공유 가능

Docker Hub이란?

  • https://hub.docker.com
  • Docker가 제공해주는 서비스로 Docker Image를 공유하고 찾기 위한 서비스
  • Teams & Organizations
  • Official Images
  • Github과 연동을 통한 Automated Build 제공

Practice 1 : 간단한 Hello World 프로그램

node.js로 만든 간단한 프로그램을 단계별로 이미지 빌드부터 최종적으로 다른 서버에서 실행까지 전체 과정을 다뤄보는 practice

만들려는 프로그램 개요

  • Node.js로 구성된 초간단 웹 서비스
    a. app.js가 전부
    b. 하지만 node 런타임 환경이 필요
  • 보통 이를 실행하려면
    a. node app.js
  • 단 node 환경이 설정되어 있어야함

Docker 없이 만들려는 프로그램 실행 시

  • 직접 설치/실행 시 순서
    a. OS선택
    b. Node 설치
    c. 코드 복사
    d. 프로그램 실행 (node app.js)
    -> 이 내용을 Dockerfile에 기술하면 Docker Image 생성이 가능하다.

Dockerfile의 생성

  • Docker에게 소프트웨어 설치 명령을 기술
  • 먼저 베이스 이미지를 기술 (FROM)
  • 다음으로 코드 복사
  • 마지막으로 코드 실행
FROM node:alpine #OS 종류를 적어줌. 여기서는 Alpine이라는 경량 리눅스를 데모 목적으로 선택
COPY . /app # COPY : 코드 복사에 사용, 현재 디렉토리 내용을 dockerimage의 app폴더 밑으로
WORKDIR /app # WORKDIR: Working directory를 지정
CMD node app.js # CMD: 실행하는 명령 앞에 지정

Dockerfile 사용 가능 기타 키워드

  • ARG : Docker Image를 만들 때 사용되는 변수 지정. 최종 이미지에는 안 들어감.
  • ENV : 컨테이너가 실행될 때 사용되는 환경변수. 최종 이미지에 저장됨
  • USER : 컨테이너를 실행할 때 사용할 유저 ID
  • EXPOSE : 서비스 사용 포트번호
  • RUN :
    • 빌드시 실행되어야 하는 명령들이 지정됨 (docker build)
    • RUN apt-get update && apt-get install -y curl

Dockerfile 키워드 : CMD vs ENTRYPOINT (1)

  • Container가 시작할 때 실행되어야 하는 명령어를 지정하는데 사용 (docker run)

    • 굉장히 흡사한 기능을 제공하지만 우선 순위가 있음
  • 둘다 한 DOCKERFILE에서 여러번 실행되면 각각 마지막 것만 사용됨

  • 아래의 경우 docker run 실행 시 동일한 결과가 나옴

  • CMD
    CMD ["command1.sh"]
    CMD ["command2.sh"]

  • ENTRYPOINT
    ENTRYPOINT ["command1.sh"]
    ENTRYPOINT ["command2.sh"]

둘다 쓰이면 ENTRYPOINT가 우선순위
ENTRYPOINT 안쓰고 CMD만 쓰는게 best practice.
둘다 컨테이너 실행 시 command2.sh 스크립트가 실행됨(마지막것만)

Dockerfile 키워드 : CMD vs ENTRYPOINT (2)

  • CMD나 ENTRYPOINT 중 하나만 지정되면 그게 container가 실행될 때 실행

FROM debian:buster

COPY ./myproject
RUN apt-get update ...
CMD ["./cmd1.sh"]

docker run my-image
=> ./cmd1.sh가 기본으로 실행됨

docker run my-image cmd2.sh
=> cmd2.sh가 실행됨

Dockerfile 키워드 : CMD vs ENTRYPOINT (3)

  • 둘이 한 DOCKERFILE에서 같이 지정가능함
  • 둘이 같이 사용되면 ENTRYPOINT가 기본 명령이 되고 CMD가 인자를 제공
  • ENTRYPOINT는 --entrypoint 옵션을 통해서만 덮어쓰기가 가능

CMD or ENTRYPOINT ?

  • 최대한 CMD만 사용
  • ENTRYPOINT를 사용하면 실행시 타이핑을 덜 할 수 있음
    • 파라미터를 지정해주면 되기 때문이지만 감춰지기 때문에 오히려 혼란을 줄 수 있음

요약 :
1. ENTRYPOINT가 있으면 CMD값이 파라미터로 실행됨
2. 아니면 CMD가 실행됨

Dockerfile 살펴보기 ex) Airflow

# VERSION 1.10.9
# AUTHOR: Matthieu "Puckel_" Roisil
# DESCRIPTION: Basic Airflow container
# BUILD: docker build --rm -t puckel/docker-airflow .
# SOURCE: https://github.com/puckel/docker-airflow

FROM python:3.7-slim-buster
LABEL maintainer="Puckel_"

# Never prompt the user for choices on installation/configuration of packages
ENV DEBIAN_FRONTEND noninteractive
ENV TERM linux

# Airflow 
ARG AIRFLOW_VERSION=1.10.9
ARG AIRFLOW_USER_HOME=/usr/local/airflow
ARG AIRFLOW_DEPS=""
ARG PYTHON_DEPS=""
ENV AIRFLOW_HOME=${AIRFLOW_USER_HOME}

# Define en_US.
ENV LANGUAGE en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV LC_CTYPE en_US.UTF-8
ENV LC_MESSAGES en_US.UTF-8

# Disable noisy "Handling signal" log messages:
# ENV GUNICORN_CMD_ARGS --log-level WARNING

RUN set -ex \
  && buildDeps=' \
      freetds-dev \
      libkrb5-dev \
      libsasl2-dev \
      libssl-dev \
      libffi-dev \
      libpq-dev \
      git \
  ' \
  && apt-get update -yqq \
  && apt-get upgrade -yqq \
  && apt-get install -yqq --no-install-recommends \
      $buildDeps \
      freetds-bin \
      build-essential \
      default-libmysqlclient-dev \
      apt-utils \
      curl \
      rsync \
      netcat \
      locales \
  && sed -i 's/^# en_US.UTF-8 UTF-8$/en_US.UTF-8 UTF-8/g' /etc/locale.gen \
  && locale-gen \
  && update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \
  && useradd -ms /bin/bash -d ${AIRFLOW_USER_HOME} airflow \
  && pip install -U pip setuptools wheel \
  && pip install pytz \
  && pip install pyOpenSSL \
  && pip install ndg-httpsclient \
  && pip install pyasn1 \
  && pip install apache-airflow[crypto,celery,postgres,hive,jdbc,mysql,ssh${AIRFLOW_DEPS:+,}${AIRFLOW_DEPS}]==${AIRFLOW_VERSION} \
  && pip install 'redis==3.2' \
  && if [ -n "${PYTHON_DEPS}" ]; then pip install ${PYTHON_DEPS}; fi \
  && apt-get purge --auto-remove -yqq $buildDeps \
  && apt-get autoremove -yqq --purge \
  && apt-get clean \
  && rm -rf \
      /var/lib/apt/lists/* \
      /tmp/* \
      /var/tmp/* \
      /usr/share/man \
      /usr/share/doc \
      /usr/share/doc-base

COPY script/entrypoint.sh /entrypoint.sh
COPY config/airflow.cfg ${AIRFLOW_USER_HOME}/airflow.cfg

RUN chown -R airflow: ${AIRFLOW_USER_HOME}

EXPOSE 8080 5555 8793

USER airflow
WORKDIR ${AIRFLOW_USER_HOME}
ENTRYPOINT ["/entrypoint.sh"]
CMD ["webserver"]
# => /entrypoint.sh webserver 이런식으로 실행됨

ENV: 최종 이미지에 들어감
ARG : 빌드할 때만 사용하며 이미지에는 안들어감

RUN ~ : 빌드할 때 실행되는 명령

Docker Image 생성

$ docker build --platform linux/amd64 -t hello-world-docker .
 => [internal] load build definition from Dockerfile
…
 => => writing image
sha256:cb6c638168780afd3d74fc1cddd813917a6a397dad453c8e1a8063635c1521fe 0.0s
 => => naming to docker.io/library/hello-world-docker

docker build를 실행하면 Dockerfile에서 RUN 명령이 실행됨
--platform linux/amd64 : 만일 Apple M1 chip 기반 맥에서 빌드하는 경우 그 이미지는 ARM 기반 아키텍처로 만들어지기 때문에 일반 리눅스에서 안 돌아감. 그래서 --platform 옵션을 사용해서 linux/amd64로 지정
-t hello-world-docker : -t는 태그를 지정하는 것으로 뒤에서 더 설명

Docker Image 확인

$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world-docker latest cb6c63816878 22 minutes ago 179MB

Docker Container로 실행

$ docker run hello-world-docker # docker run을 Dockerfile에서 CMD 명령이 실행됨
Hello Docker!
  • 만일 이 이미지를 다른 컴퓨터에서 실행하고자 한다면?
  • Docker Registry (예를 들면 Docker hub)으로 먼저 등록

Docker Hub 소개

Docker hub에 repo로 등록하고 새로운 리눅스 서버에서 다운로드받은 후에 거기에서 컨테이너 구동

Docker Registry에 등록

  • Docker Hub 회원등록

  • Create repository 선택

  • 이름을 "hello-world-docker"로 지정. Public 속성 지정:

    • yjbenkang/hello-world-docker
  • 터미널로 이동하여 다음 명령을 실행

  • 먼저 현재 이미지의 repo 이름을 yjbenkang/hello-world-docker로 변경

$ docker image ls
$ docker tag hello-world-docker:latest yjbenkang/hello-world-docker:latest
$ docker image ls

$ docker login --username=yjbenkang # 이 때 패스워드를 별도 프롬프트에서 물어봄
$ docker push yjbenkang/hello-world-docker

  • 위의 명령 실행 후 Docker Hub에서 레포에 이미지가 잘 올라갔는지 결과 확인

Docker Hub로부터 받은 Image 실행

다른 서버에서 이미지를 다운로드 받아 컨테이너로 실행하기

  • https://labs.play-with-docker.com/ 를 사용해서 4시간동안 서버를 하나 무료로 사용

  • Docker Hub에 로그인이 되어있다면 그냥 계정 연결을 허용하면 됨

  • 터미널 윈도우를 Option + Enter(윈도우는 Alt+Enter)로 최대화하고 아래 명령 실행

    • docker version
    • docker pull yjbenkang/hello-world-docker
    • docker image ls
    • docker run yjbenkang/hello-world-docker


      너무 느린관계로 run은 실행못했음..

만일 로컬에 다운로드 받은 이미지가 없다면 docker hub에서 pull을 알아서 수행함

실행시 아래 에러가 난다면 build할때 --platform 옵션 사용
필요:
WARNING: The requested image's platform
(linux/arm64/v8) does not match the detected host
platform (linux/amd64/v3) and no specific platform was
requested exec /usr/local/bin/docker-entrypoint.sh: exec
format error

Docker Desktop에서 로그인

  • Docker Desktop에서 Docker Hub으로 로그인해두면 Desktop에서 Pull, Push 등을 수행 가능

위에서 사용한 Docker 명령 요약

push & pull은 docker login으로 인증 먼저

  • docker version
  • docker build -t [이미지이름]:[버전정보]
  • docker push : docker registry에 업로드
  • docker tag : 내가 이미 만든 이미지의 이름을 다른 이름으로 변경, 이미지 이름 바꿀 때 혹은 이미지의 버전이나 태그를 다른걸로 바꿀 때 사용 (별칭을 만드는거지 이름을 아예 새로 바꾸는게 아님)
  • docker pull : test나 prod 서버에서 남이 만들어서 업로드해놓은 도커 이미지를 내가 작업중인 서버로 다운로드 받을 때 사용
  • docker run : 컨테이너 시작, dockerfile의 entrypoint 세팅되어있으면 cmd의 값을 파라미터로 받아서 할거고, cmd만 있으면 cmd가 실행됨
    • p option (port mapping)
    • v option (volume mapping)

docker run vs docker exec

  • docker run과 docker exec의 차이점은 무엇일까 ?
  • docker run은 새로 Container를 실행하는 것
  • docker exec는 실행된 Container에 작업을 하는 것
    • 그래서 이 명령은 Container ID가 필요함
  • 두 명령 모두 --user root 혹은 -u root를 통해 루트 유저로 연결가능

Docker Image 이름

  • docker image ls와 docker images는 동일한 결과를 보여줌

  • 앞서 docker tag 명령의 경우 별칭을 만들어주는 것임 (이름을 바꾸는 것이 아님)

    • docker tag hello-world-docker yjbenkang/hello-world-docker
  • Docker image의 실제 ID는 IMAGE ID임

  • Image 이름 자체는 REPOSITORY 이름과 TAG로 구성됨

    • 한번에 쓰는 경우 :을 사이에 두고 같이 씀 -> redis:13, yjbenkang/hello-world-docker:latest
  • docker image ls에서 Repository에 해당

    • Docker Hub에서 다운로드받은 것이라면 어카운트ID(네임스페이스)를 포함할 수 있음
    • 하지만 공식이미지는 네임스페이스가 없음
  • 포맷: Repo이름:태그

    • 예: yjbenkang/hello-world-docker:latest
    • 예: bitnami/airflow
    • 예: hello-world-docker:latest
  • 공식 이미지들의 경우에는 네임스페이스가 없음

    • 예: ubuntu:18.04
    • 예: node:alpine

Docker tag란?

  • Docker Image의 버전이나 변형을 나타내는 문자열
    • 디폴트 값은 latest
    • Docker Image의 부가정보를 나타냄
  • Docker Image 이름에서 :뒤에 해당
    • 예: ubuntu:18.04
    • 예: bitnami/airflow
    • 예: node:alpine

Practice 2 : Ubuntu 컨테이너로 실행

리눅스 커널과 배포판

  • 리눅스 커널: 리눅스의 핵심부분(자동차로 치면 엔진). Linus B. Torvalds가 1992년에 처음 공개

어떤 리눅스 배포판이 있는가?

  • 우분투 : 가장 많이 사용되며 데비안에 기반해서 만들어진 리눅스 배포판
  • 데비안
  • 알파인 : 임베드 시스템에서 사용할 용도로 만들어진 경량화 리눅스 배포판
  • 페도라
  • 센트OS
    ...

배포판에 따라 다른 패키지 매니저가 존재
npm, yarn, pip, apt, NuGet

우분투 설치 후 다양한 명령 실행해보기

보통은 docker image를 pull하고 run을 해야함. 바로 run하면?

  • docker run ubuntu
  • docker ps
  • docker ps -a
    docker run -it ubuntu
    • nano
    • apt list
    • apt install nano
    • apt update
    • apt install nano
    • nano
    • apt remove nano


local에서 이미지를 찾을 수 없어 dockerhub에서 퍼블릭 이미지를 가져온다.
docker ps를 해보면 ubuntu 컨테이너를 확인할 수 없다.
docker ps -a를 해보면 종료되었던 ubuntu 컨테이너를 확인할 수 있다.
docker run ubuntu로 그냥 실행하면 바로 끝나버린다.

docker run -it ubuntu
-it : interactive옵션이다. ubuntu로 오피셜 이미지를 주고 실행

이번에는 shell script사용해서 우분투 도커 컨테이너로 이동됨. root 어카운트로 들어간걸 확인할 수 있고, 패키지 설치가 가능해짐

apt update로 outdate된 apt 를 업뎃해준다.

apt install nano잘됨
nano는 에디터.끝내고 싶으면 ctrl + x

Practice 3 : MySQL 8.0 Docker로 실행

  • 먼저 Docker Engine이 실행된 것 확인하고 terminal 프로그램 실행
  • MySQL docker image를 다운로드
    • docker pull mysql/mysql-server:8.0
  • 다운로드 받은 이미지로 Docker container 실행
    • docker run --name=mysql_container mysql/mysql-server:8.0
  • MySQL root 계정의 패스워드 찾기
    • docker logs mysql_container 2>&1 | grep GENERATED
  • 마지막으로 MySQL shell 실행하기
    • docker exec -it mysql_container mysql -uroot -p
      • 어떤 프로그램 실행할 것인지에 대해서 mysql 입력해서 mysql shell을 실행, -u옵션으로 root유저로 로그인, -p으로 password입력하겠다 선언

여기서 사용하는 Docker 명령

  • docker run --name
    • 기억하기 쉬운 이름을 docker ps로 찾은 Container ID대신 사용 가능
  • docker logs
    • Container쪽에서 생성된 stdout, stderr단의 로그를 읽어옴
    • --follow 옵션을 사용하면 로그가 계속적으로 스트리밍이 됨

profile
keep growing

0개의 댓글