실전용 Docker 기초 정리

코드짜는침팬지·2023년 10월 28일
0

학부 연구생

목록 보기
7/10
post-thumbnail

논문을 읽고 코드를 실행시키다 보니 어떤건 우분투 18 어떤건 20 어떤건 22
어떤건 gcc7.5 어떤건 9.5 CMake는 뭘 쓰고 어쩌고 저쩌고
환경설정하다 정신이 나가버려서 결국 docker를 써보기로 했습니다.
요즘 황금방패가 점점 더 세지는 느낌인데 울고싶네요.

Docker는 도대체 왜쓸까

저는 아나콘다 환경을 사용하는걸 선호합니다. 사실 아나콘다로 대부분의 문제는 해결 가능했거든요
Docker와 Anaconda(특히 conda env)는 모두 독립적인 환경을 제공하는 도구입니다.
그러나 주요 사용 사례와 방식에는 중요한 차이점이 있습니다.

  1. 목적:

    • Anaconda (conda env): 주로 Python과 관련된 패키지와 의존성을 관리하고 독립적인 Python 환경을 제공하는 데 중점을 둡니다.
    • Docker: 애플리케이션과 그 의존성 전체 (운영 체제, 라이브러리, 코드 등)를 패키징하여 어디에서나 동일하게 실행할 수 있게 하는 것을 목표로 합니다.
  2. 범위:

    • Anaconda (conda env): 주로 Python 환경 내에서의 패키지 관리에 초점을 맞춥니다.
    • Docker: 전체 운영 체제 수준에서의 격리를 제공하여, 다양한 언어, 라이브러리, 도구, 서비스 등을 포함하는 전체 애플리케이션 스택을 패키징합니다.
  3. 격리 수준:

    • Anaconda (conda env): Python 패키지와 환경 변수 등 Python 환경에 한정된 격리를 제공합니다.
    • Docker: OS 수준의 격리를 제공하여, 컨테이너마다 별도의 파일 시스템, 네트워크, 프로세스 공간 등을 가집니다.

요약하면, Docker는 "코드와 모든 의존성을 포함하는 컨테이너"를 제공하여, 어디에서나 동일하게 실행할 수 있게 합니다. 이는 마치 "컴퓨터 안의 작은 컴퓨터"와 같은 개념입니다. 반면, Anaconda의 conda env는 특정 Python 환경을 격리하여 관리하는 데 중점을 둡니다.
그니까 docker로 만든 이미지로 컴퓨터를 쓰면 기존 컴퓨터에서 사용하고 있던 폴더는 사용 못합니다.
컴퓨터 안에 따로 image를 써서 docker로 컴퓨터 os를 하나 더 만든거거든요

핵심은 컴퓨터 안에 작은 컴퓨터라는 개념인데 그럼 여기서 의문이 생깁니다.

이거 왜 안쓰는데?
가상머신이라는 좋은거 냅두고 굳이 도커를 쓰는건 이유가 있습니다.

Docker와 전통적인 가상 머신(VM)은 모두 애플리케이션을 격리된 환경에서 실행하는 데 사용되지만, 접근 방식과 특징에는 여러 차이점이 있습니다.
이제 주요 차이점과 Docker의 장점을 살펴보겠습니다:

  1. 경량성:

    • Docker: Docker 컨테이너는 호스트 OS의 커널(Window,ubuntu 등)을 공유하며, 별도의 OS를 포함하지 않기 때문에 매우 가볍습니다. 이로 인해 컨테이너는 빠르게 시작되고, 적은 리소스를 사용합니다.
    • VM: 각 VM은 전체 운영 체제와 그에 필요한 리소스를 포함하므로 더 많은 디스크 공간, 메모리 및 CPU 리소스가 필요합니다.
  2. 시작 시간:

    • Docker: 컨테이너는 몇 초 안에 시작될 수 있습니다.
    • VM: VM은 전체 운영 체제를 부팅해야 하므로 시작하는 데 더 많은 시간이 걸립니다.
  3. 간편함:

    • Docker: Docker 이미지는 어디에서나 동일하게 실행될 수 있습니다. 이는 개발, 테스트 및 프로덕션 환경 간의 일관성을 보장합니다.
    • VM: VM은 하드웨어 추상화 레벨에서 작동하므로, 다른 환경으로의 이동이 더 복잡할 수 있습니다.
  4. 관리 및 유지 보수:

    • Docker: Dockerfile을 사용하여 이미지를 구성하고 빌드할 수 있습니다. 이를 통해 애플리케이션과 그 의존성을 코드로 관리할 수 있습니다.
    • VM: VM은 일반적으로 수동으로 구성되며, 이러한 구성을 버전 관리하거나 코드로 관리하기가 어렵습니다.
  5. 리소스 효율성:

    • Docker: 여러 컨테이너가 동일한 호스트에서 실행될 때, 필요한 리소스만큼만 사용하며, 리소스를 효율적으로 공유합니다.
    • VM: 각 VM은 고정된 리소스 할당을 가집니다.
  6. 보안:

    • Docker: 컨테이너는 호스트 OS의 커널을 공유하기 때문에, 커널 보안 기능과 컨테이너 격리 기능에 의존합니다.
    • VM: 각 VM은 완전히 격리된 환경을 제공하므로, 보안 면에서 더 강력할 수 있습니다.

결론적으로, Docker는 경량성, 빠른 시작 시간, 간편함, 효율적인 리소스 사용 등의 장점을 제공합니다.
이러한 이유로, 특히 마이크로서비스 아키텍처, CI/CD 파이프라인, 개발-테스트-배포의 일관성 유지 등의 사용 사례에서 Docker가 널리 선호되고 있습니다.

Docker 시작하기: 설치부터 배포까지

1. Docker란?

Docker는 애플리케이션과 그 의존성을 컨테이너라는 격리된 환경에 패키징하여 일관된 방식으로 실행할 수 있게 해주는 플랫폼입니다.

  • 이미지: 애플리케이션, 의존성, 라이브러리, 실행 파일 및 설정을 포함하는 패키지.
  • 컨테이너: 이미지를 실행하는 런타임 인스턴스. 독립적인 환경을 제공하여 애플리케이션 간 격리를 보장합니다.

2. Docker 설치하기

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

3. Dockerfile 작성하기

Dockerfile은 Docker 이미지를 생성하기 위한 스크립트입니다.

Dockerfile의 기본 구성 요소:

  1. FROM: 기본 이미지를 지정합니다. 예: FROM ubuntu:18.04
  2. MAINTAINER: 이미지의 작성자 정보를 지정합니다. 예: MAINTAINER yourname@email.com
  3. RUN: 이미지를 빌드할 때 실행할 명령어를 지정합니다. 예: RUN apt-get update
  4. CMD: 컨테이너가 시작될 때 실행할 기본 명령어를 지정합니다. 예: CMD ["echo", "Hello World"]
  5. ENTRYPOINT: 컨테이너가 시작될 때 실행할 명령어를 지정합니다. CMD와 비슷하지만, 컨테이너 실행 시 전달되는 인수를 받을 수 있습니다.
  6. WORKDIR: 작업 디렉토리를 설정합니다. 예: WORKDIR /app
  7. ENV: 환경 변수를 설정합니다. 예: ENV MY_VARIABLE=value
  8. ADD: 파일이나 디렉토리를 이미지에 추가합니다.
  9. COPY: 파일이나 디렉토리를 이미지에 복사합니다.
  10. EXPOSE: 컨테이너에서 사용할 포트를 지정합니다. 예: EXPOSE 80
  11. VOLUME: 볼륨을 생성하거나 마운트합니다. 예: VOLUME /data

포트 설명:

  • EXPOSE: Dockerfile의 EXPOSE 명령어는 이미지가 런타임에 지정된 네트워크 포트에서 수신 대기해야 함을 나타냅니다. 그러나 EXPOSE만으로는 포트를 실제로 열지 않습니다.
    예: EXPOSE 80은 컨테이너가 포트 80에서 수신 대기해야 함을 나타냅니다.

  • -p 플래그: docker run 명령어의 -p 플래그를 사용하여 호스트와 컨테이너 간의 포트 매핑을 지정할 수 있습니다.
    예: docker run -p 8080:80 image_name은 호스트의 8080 포트를 컨테이너의 80 포트에 매핑합니다.

  • -P 플래그: docker run 명령어의 -P 플래그를 사용하면 Docker가 자동으로 호스트의 사용 가능한 포트를 컨테이너의 EXPOSE로 지정된 포트에 매핑합니다.

  • 포트 충돌: 동일한 호스트 포트에 여러 컨테이너를 매핑하려고 하면 포트 충돌이 발생할 수 있습니다. 이 경우, 다른 호스트 포트를 사용해야 합니다.

  • 포트 범위: 범위를 사용하여 여러 포트를 한 번에 EXPOSE하거나 매핑할 수 있습니다.
    예: EXPOSE 7000-8000 또는 docker run -p 7000-8000:7000-8000 image_name

포트는 컴퓨터 네트워크에서 특정 프로세스나 서비스가 네트워크 서비스를 제공하기 위해 사용하는 엔드포인트입니다.
우분투의 telnet과 같은 도구를 사용하여 특정 포트가 열려 있는지 확인할 수 있습니다.

Docker에서 포트는 두 가지 주요한 목적으로 사용됩니다:

  1. 컨테이너 내부의 서비스 접근: 컨테이너 내부에서 실행되는 서비스 (예: 웹 서버, 데이터베이스 서버 등)는 특정 포트에서 수신 대기합니다. 이 포트를 통해 서비스에 접근할 수 있습니다.

  2. 호스트와 컨테이너 간의 포트 매핑: Docker는 호스트 시스템의 포트와 컨테이너 내부의 포트를 매핑하는 기능을 제공합니다. 이를 통해 외부에서 호스트의 특정 포트로 요청을 보내면 그 요청이 컨테이너의 특정 포트로 전달됩니다.

예를 들어, 컨테이너 내부에서 웹 서버가 포트 80에서 실행되고 있을 때, docker run -p 8080:80 image_name 명령어를 사용하여 호스트의 8080 포트와 컨테이너의 80 포트를 매핑하면, 외부에서 호스트의 8080 포트로 웹 요청을 보내면 그 요청이 컨테이너의 웹 서버로 전달됩니다.

이렇게 포트 매핑을 사용하면 여러 컨테이너가 동일한 서비스 (예: 웹 서버)를 제공하더라도 각 컨테이너에 대해 다른 호스트 포트를 사용하여 접근할 수 있습니다.

다음은 간단한 예제입니다.

# 베이스 이미지 설정
FROM ubuntu:20.04

# 작업 디렉토리 설정
WORKDIR /app

# 의존성 설치
RUN apt-get update && apt-get install -y python3

# 애플리케이션 코드 추가
COPY . /app

# 포트 설정
EXPOSE 80

# 컨테이너 실행 시 실행될 명령어 설정
CMD ["python3", "app.py"]

4. Docker 이미지 생성 및 배포

# 이미지 빌드
docker build -t myapp:latest .

# 이미지 실행 (컨테이너 생성 및 시작)
docker run -d -p 80:80 myapp:latest

# Docker Hub에 이미지 푸시
docker login
docker push myapp:latest

5. Docker 컨테이너 관리

Docker에서 컨테이너를 사용하고 관리하는 방법에 대해 간략하게 설명하겠습니다.

1. 컨테이너 실행:

Docker 이미지를 기반으로 컨테이너를 실행합니다.

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

예시:

docker run -d -p 8080:80 nginx

이 명령은 nginx 이미지를 기반으로 컨테이너를 백그라운드(-d)에서 실행하며, 호스트의 8080 포트와 컨테이너의 80 포트를 연결(-p 8080:80)합니다.

2. 실행 중인 컨테이너 목록 보기:

docker ps

모든 컨테이너(실행 중이지 않은 컨테이너 포함)를 보려면:

docker ps -a

3. 컨테이너에 접속:

실행 중인 컨테이너에 bash 셸로 접속하려면:

docker exec -it [CONTAINER_ID or CONTAINER_NAME] /bin/bash

예시:

docker exec -it my_container /bin/bash

4. 컨테이너 중지:

docker stop [CONTAINER_ID or CONTAINER_NAME]

5. 컨테이너 재시작:

docker restart [CONTAINER_ID or CONTAINER_NAME]

6. 컨테이너 삭제:

컨테이너를 삭제하기 전에 먼저 중지해야 합니다.

docker rm [CONTAINER_ID or CONTAINER_NAME]

7. 컨테이너 로그 보기:

docker logs [CONTAINER_ID or CONTAINER_NAME]

8. 컨테이너 내부의 파일 복사:

컨테이너에서 호스트로 파일 또는 디렉토리를 복사하려면:

docker cp [CONTAINER_ID or CONTAINER_NAME]:[CONTAINER_PATH] [HOST_PATH]

예시:

docker cp my_container:/app/data.txt ./data.txt

9. 호스트에서 컨테이너 파일 복사:

docker cp /path/to/local/file container_id:/path/to/container/directory

여기서:

  • /path/to/local/file는 호스트 시스템에서 파일의 경로입니다.
  • container_id는 파일을 복사하려는 대상 컨테이너의 ID 또는 이름입니다.
  • /path/to/container/directory는 컨테이너 내에서 파일을 저장할 경로입니다.

예를 들어, 로컬의 Dockerfilemycontainer라는 이름의 컨테이너의 /app 디렉토리로 복사하고 싶다면 다음과 같이 명령을 실행합니다:

docker cp Dockerfile mycontainer:/app

이 명령을 실행하면 Dockerfile이 컨테이너의 /app 디렉토리로 복사됩니다.

10.docker 컨테이너 이름 변경하기

Docker 컨테이너의 이름을 변경하려면 기존 컨테이너를 중지하고 새 이름으로 새 컨테이너를 생성해야 합니다. Docker는 직접적으로 실행 중인 컨테이너의 이름을 변경하는 기능을 제공하지 않습니다. 하지만, 컨테이너를 중지한 후에 이름을 변경할 수 있습니다.

다음 단계를 따라 컨테이너의 이름을 변경할 수 있습니다:

  1. 기존 컨테이너를 중지합니다.

    docker stop festive_cori
  2. 컨테이너의 이름을 변경합니다.

    docker rename festive_cori f2nerf
  3. 필요하다면, 새 이름으로 컨테이너를 다시 시작합니다.

    docker start f2nerf

이제 컨테이너의 이름이 f2nerf로 변경되었습니다. docker ps -a 명령어를 사용하여 변경된 이름을 확인할 수 있습니다.

6. NVIDIA GPU와 Docker

Docker에서 GPU를 사용하려면 NVIDIA GPU 드라이버와 NVIDIA Container Toolkit을 설치해야합니다.

  • NVIDIA GPU 드라이버 설치: NVIDIA 공식 웹사이트에서 호환되는 드라이버를 다운로드하고 설치합니다.

  • NVIDIA Container Toolkit 설치:

    sudo apt-get install nvidia-docker2
    sudo systemctl restart docker

    Docker 실행 시 --gpus all 옵션을 추가하여 GPU를 활성화합니다.
    docker run --gpus all image-name

컨테이너 만들고 실행 안 될때

nvidia-docker run -it --shm-size 100g --name '容器名称' -v /data0/用户名/:/workspace -v /data0/dataset/:/datasets emernerf:latest

profile
학과 꼴찌 공대 호소인

0개의 댓글