Docker run 명령 매개변수

DockerBeginner
지금 연습하기

소개

이 실습에서는 docker run 명령과 다양한 매개변수만 집중적으로 다룹니다. docker run은 Docker를 사용할 때 기본이 되는 명령으로, 특정 설정을 적용해 컨테이너를 만들고 시작할 수 있습니다.

이 명령의 매개변수를 익히면 컨테이너화된 애플리케이션을 더 세밀하게 제어하고 Docker 컨테이너를 효과적으로 배포하고 관리할 수 있습니다.

이름 지정, 분리 모드, 포트 매핑, 볼륨 마운트, 환경 변수, 리소스 제한 등을 포함한 다양한 매개변수를 다룹니다.

이미 알고 있는 매개변수도 있고, 새롭게 접하는 매개변수도 있을 수 있습니다.

Docker run 기초와 컨테이너 이름 지정

이 단계에서는 docker run의 기본 사용법을 익히고 컨테이너 이름을 지정하는 방법을 살펴봅니다.

먼저 기본 Nginx 컨테이너를 실행합니다.

docker run nginx

이 명령은 Nginx 컨테이너를 포그라운드에서 실행합니다. 터미널에 로그가 계속 출력됩니다. 컨테이너가 포그라운드에서 실행되므로 로그가 터미널에 직접 표시됩니다.

컨테이너를 중지하려면 Ctrl+C를 누릅니다. 중지하는 데 몇 초 정도 걸릴 수 있습니다. Docker가 컨테이너를 정상적으로 종료할 시간을 주는 것이므로 이는 정상입니다.

이번에는 컨테이너를 분리 모드로 실행하고 이름을 지정합니다.

docker run -d --name my-nginx nginx

명령을 구성 요소별로 살펴보겠습니다.

  • docker run: 컨테이너를 실행하는 기본 명령입니다.
  • -d: 컨테이너를 분리 모드, 즉 백그라운드에서 실행합니다. 터미널에는 출력이 표시되지 않습니다.
  • --name my-nginx: 컨테이너 이름을 "my-nginx"로 지정합니다. 이름을 지정하지 않으면 Docker가 임의의 이름을 지정합니다.
  • nginx: 컨테이너를 만드는 데 사용할 이미지의 이름입니다.

명령을 실행하면 긴 문자열이 출력됩니다. 이 문자열은 컨테이너 ID입니다. Docker가 컨테이너를 백그라운드에서 시작한 것입니다.

이름이 이미 사용 중이라는 오류가 표시되면 해당 이름을 사용하는 컨테이너가 이미 있다는 뜻입니다. 다른 이름을 선택하거나 기존 컨테이너를 삭제할 수 있습니다. 기존 컨테이너를 삭제하는 방법은 이후 실습에서 배웁니다.

포트 매핑

이 단계에서는 docker run의 -p 매개변수를 사용해 컨테이너의 포트를 호스트에 매핑합니다. 이렇게 하면 호스트 컴퓨터에서 컨테이너 내부에서 실행 중인 서비스에 접근할 수 있습니다.

포트를 매핑해 Nginx 컨테이너를 실행합니다.

docker run -d --name nginx-mapped -p 8080:80 nginx

새로 추가된 명령 부분을 살펴보겠습니다.

  • -p 8080:80: 호스트의 8080 포트를 컨테이너의 80 포트에 매핑합니다. 형식은 항상 host_port:container_port입니다.

Nginx는 기본적으로 컨테이너 내부의 80 포트에서 실행됩니다. 이 포트를 호스트의 8080 포트에 매핑했으므로 웹 브라우저에서 localhost:8080으로 이동해 Nginx에 접근할 수 있습니다.

이제 Nginx 환영 페이지에 접근할 수 있는지 확인합니다. 명령줄에서 HTTP 요청을 보낼 수 있는 curl 명령을 사용합니다.

curl --retry 5 --retry-all-errors --retry-delay 1 http://localhost:8080

Nginx 환영 페이지의 HTML이 출력되어야 합니다. curl이 설치되어 있지 않다면 다음 명령으로 설치합니다.

sudo apt-get update && sudo apt-get install -y curl

페이지에 계속 접근할 수 없다면 다음 항목을 확인합니다.

  • 컨테이너가 실행 중인지 확인합니다: docker ps | grep nginx-mapped
  • 포트가 실제로 매핑되었는지 확인합니다: docker port nginx-mapped
  • 클라우드 서버를 사용 중이라면 방화벽에서 8080 포트의 트래픽을 허용하는지 확인합니다.

볼륨 마운트

이 단계에서는 docker run의 -v 매개변수를 사용해 볼륨을 마운트하고 호스트와 컨테이너 간에 데이터를 공유합니다. 이 방법은 데이터를 유지하거나 컨테이너에 설정 파일을 제공할 때 유용합니다.

먼저 호스트에 간단한 디렉터리 구조를 만듭니다.

mkdir -p ~/project/nginx-data
echo "<html><body><h1>Hello from mounted volume</h1></body></html>" > ~/project/nginx-data/index.html

이 명령은 다음 작업을 수행합니다.

  • 홈 디렉터리의 project 디렉터리 안에 nginx-data 디렉터리를 만듭니다.
  • 새 디렉터리 안에 index.html이라는 간단한 HTML 파일을 만듭니다.

이제 Nginx 컨테이너를 실행하고 이 디렉터리를 마운트합니다.

docker run -d --name nginx-volume -p 8081:80 -v ~/project/nginx-data:/usr/share/nginx/html nginx

명령을 구성 요소별로 살펴보겠습니다.

  • docker run: 새 컨테이너를 실행하는 명령입니다.
  • -d: 컨테이너를 분리 모드, 즉 백그라운드에서 실행합니다.
  • --name nginx-volume: 컨테이너 이름을 "nginx-volume"으로 지정합니다.
  • -p 8081:80: 호스트의 8081 포트를 컨테이너의 80 포트에 매핑합니다.
  • -v ~/project/nginx-data:/usr/share/nginx/html: 호스트의 nginx-data 디렉터리를 컨테이너의 /usr/share/nginx/html 디렉터리에 마운트합니다. Nginx는 이 디렉터리에서 제공할 콘텐츠를 찾습니다.
  • nginx: 컨테이너를 만드는 데 사용할 이미지의 이름입니다.

이제 사용자 지정 페이지가 제공되는지 확인합니다.

curl --retry 5 --retry-all-errors --retry-delay 1 http://localhost:8081

사용자 지정 HTML 파일의 내용인 "Hello from mounted volume!"이 출력되어야 합니다.

사용자 지정 콘텐츠가 보이지 않는다면 다음 항목을 확인합니다.

  • 호스트 시스템에 ~/project/nginx-data/index.html 파일이 있는지 확인합니다.
  • 컨테이너가 실행 중인지 확인합니다: docker ps | grep nginx-volume
  • Nginx 로그에 오류가 있는지 확인합니다: docker logs nginx-volume

호스트 디렉터리를 컨테이너에 마운트하는 이 방법을 바인드 마운트라고 합니다. 호스트와 컨테이너 간에 파일을 공유하는 간단한 방법입니다. 다음 사항을 기억합니다.

  • 호스트 디렉터리 경로는 절대 경로여야 합니다.
  • 호스트 디렉터리가 없으면 Docker가 자동으로 만듭니다.
  • 이 디렉터리의 파일을 호스트나 컨테이너에서 변경하면 변경 사항이 양쪽에 즉시 반영됩니다.
  • 권한에 주의합니다. 컨테이너는 기본적으로 root로 실행되므로 호스트 사용자가 수정할 수 없는 파일이 만들어질 수 있습니다.

이 방법은 단일 파일이 아닌 디렉터리를 마운트하므로 "not a directory" 오류를 방지합니다. 컨테이너를 다시 만들지 않고도 파일을 더 유연하게 추가, 삭제, 수정할 수 있습니다.

환경 변수

이 단계에서는 docker run의 -e 매개변수를 사용해 컨테이너에 환경 변수를 설정합니다. 코드를 변경하지 않고 애플리케이션을 설정할 때 유용합니다.

환경 변수를 지정해 컨테이너를 실행합니다.

docker run -d --name nginx-env -e NGINX_HOST=mywebsite.com -e NGINX_PORT=80 nginx

새로 추가된 부분을 살펴보겠습니다.

  • -e NGINX_HOST=mywebsite.com: NGINX_HOST라는 환경 변수의 값을 mywebsite.com으로 설정합니다.
  • -e NGINX_PORT=80: NGINX_PORT라는 환경 변수의 값을 80으로 설정합니다.

환경 변수는 컨테이너 내부에서 실행되는 프로세스가 사용할 수 있는 키-값 쌍입니다. 많은 Docker 이미지는 설정에 특정 환경 변수를 사용하도록 설계되어 있습니다.

다음 명령으로 환경 변수를 확인합니다.

docker exec nginx-env env | grep NGINX_

이 명령은 다음 작업을 수행합니다.

  • docker exec nginx-env: Docker에 실행 중인 nginx-env 컨테이너에서 명령을 실행하도록 지시합니다.
  • env: 모든 환경 변수를 출력합니다.
  • | grep NGINX_: 출력에서 "NGINX_"가 포함된 줄만 표시합니다.

두 환경 변수가 모두 표시되어야 합니다.

환경 변수가 표시되지 않는다면 다음 항목을 확인합니다.

  • 컨테이너가 실행 중인지 확인합니다: docker ps | grep nginx-env
  • docker run 명령에서 환경 변수 이름의 철자를 올바르게 입력했는지 확인합니다.

리소스 제한

이 단계에서는 docker run의 매개변수를 사용해 컨테이너의 리소스를 제한합니다. 특히 여러 컨테이너를 실행할 때 호스트 시스템의 성능과 안정성을 관리하는 데 중요합니다.

메모리와 CPU 사용량을 제한해 컨테이너를 실행합니다.

docker run -d --name nginx-limited --memory 256m --cpus 0.5 nginx

새로 추가된 부분을 살펴보겠습니다.

  • --memory 256m: 컨테이너의 메모리를 256메가바이트로 제한합니다. 여기서 'm'은 메가바이트를 뜻합니다. 기가바이트를 뜻하는 'g'도 사용할 수 있습니다.
  • --cpus 0.5: 컨테이너가 사용할 수 있는 CPU를 최대 0.5개 코어로 제한합니다.

이 제한을 설정하면 컨테이너가 지정된 양보다 많은 리소스를 사용하지 못합니다. 따라서 컨테이너 하나가 호스트의 리소스를 독점하는 상황을 방지할 수 있습니다.

제한이 올바르게 적용되었는지 다음 명령으로 확인합니다.

docker inspect -f '{{.HostConfig.Memory}}' nginx-limited
docker inspect -f '{{.HostConfig.NanoCpus}}' nginx-limited

첫 번째 명령은 268435456(256MB를 바이트로 환산한 값)을 출력하고, 두 번째 명령은 500000000(나노 단위로 표시한 0.5 CPU)을 출력해야 합니다.

다른 값이 표시되면 docker run 명령에서 제한을 올바르게 지정했는지 확인합니다.

참고: 리소스 제한을 너무 낮게 설정하면 컨테이너의 성능이 저하되거나 컨테이너가 비정상 종료될 수 있습니다. 컨테이너에 문제가 발생하면 제한을 높여 보세요.

네트워크 설정

이 단계에서는 docker run의 --network 매개변수를 사용해 컨테이너를 네트워크에 연결합니다. 컨테이너 간 통신을 설정하거나 컨테이너 그룹을 격리할 때 유용합니다.

먼저 사용자 지정 브리지 네트워크를 만듭니다.

docker network create my-custom-network

이 명령은 my-custom-network라는 새 브리지 네트워크를 만듭니다. 브리지 네트워크는 Docker에서 가장 일반적으로 사용하는 네트워크 유형입니다.

이제 이 네트워크에 연결된 컨테이너를 실행합니다.

docker run -d --name nginx-networked --network my-custom-network nginx

--network my-custom-network 옵션은 컨테이너를 방금 만든 네트워크에 연결합니다.

같은 네트워크에 연결된 컨테이너는 서로의 컨테이너 이름을 호스트 이름으로 사용해 통신할 수 있습니다. 따라서 서비스를 쉽게 연결할 수 있습니다.

네트워크가 존재하지 않는다는 오류가 표시되면 docker network create 명령으로 네트워크를 올바르게 만들었는지 확인합니다.

재시작 정책

이 단계에서는 docker run의 --restart 매개변수를 사용해 컨테이너의 재시작 정책을 지정합니다. 이 설정을 사용하면 컨테이너가 비정상 종료되거나 Docker 데몬이 다시 시작된 경우에도 컨테이너가 계속 실행되도록 할 수 있습니다.

재시작 정책을 지정해 컨테이너를 실행합니다.

docker run -d --name nginx-restart --restart unless-stopped nginx

--restart unless-stopped 옵션은 재시작 정책을 "unless-stopped"로 설정합니다. 사용자가 직접 중지하지 않는 한 컨테이너가 자동으로 다시 시작됩니다.

다른 재시작 정책은 다음과 같습니다.

  • no: 기본값입니다. 컨테이너를 자동으로 다시 시작하지 않습니다.
  • on-failure: 컨테이너가 0이 아닌 종료 상태로 종료된 경우에만 다시 시작합니다.
  • always: 종료 상태와 관계없이 컨테이너를 항상 다시 시작합니다.

다음 명령으로 재시작 정책을 확인합니다.

docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' nginx-restart

unless-stopped가 출력되어야 합니다.

예상한 값이 표시되지 않으면 docker run 명령에서 재시작 정책을 올바르게 지정했는지 확인합니다.

작업 디렉터리와 명령

이 단계에서는 컨테이너 내부의 작업 디렉터리를 설정하고 컨테이너가 시작될 때 사용자 지정 명령을 실행하는 방법을 살펴봅니다.

docker run의 -w 매개변수는 컨테이너 내부의 작업 디렉터리를 설정합니다. 이미지 이름 뒤에 실행할 명령을 지정할 수도 있습니다.

두 가지 개념을 함께 사용해 보겠습니다.

docker run -d --name nginx-custom -w /app nginx sh -c "mkdir -p /app && touch newfile.txt && nginx -g 'daemon off;'"

명령을 구성 요소별로 살펴보겠습니다.

  • -d: 컨테이너를 분리 모드, 즉 백그라운드에서 실행합니다.
  • --name nginx-custom: 컨테이너 이름을 "nginx-custom"으로 지정합니다.
  • -w /app: 컨테이너 내부의 작업 디렉터리를 /app으로 설정합니다.
  • nginx: 사용할 이미지의 이름입니다.
  • sh -c "...": 셸 명령을 실행합니다.
    • mkdir -p /app: /app 디렉터리가 없으면 만듭니다.
    • &&: 앞의 명령이 성공한 경우에만 다음 명령을 실행합니다.
    • touch newfile.txt: newfile.txt라는 빈 파일을 만듭니다.
    • &&: 앞의 명령이 성공한 경우에만 다음 명령을 실행합니다.
    • nginx -g 'daemon off;': Nginx를 포그라운드에서 시작해 컨테이너가 계속 실행되도록 합니다.

이제 컨테이너가 실행 중이고 파일이 만들어졌는지 확인합니다.

docker ps | grep nginx-custom
docker exec nginx-custom ls -l /app/newfile.txt

첫 번째 명령은 컨테이너가 실행 중임을 보여 주어야 합니다. 두 번째 명령은 컨테이너의 /app 디렉터리에 있는 newfile.txt 파일의 세부 정보를 출력해야 합니다.

요약

이 실습에서는 docker run 명령과 다양한 매개변수 및 옵션을 자세히 살펴봤습니다. 다음 내용을 다뤘습니다.

  1. 컨테이너를 기본 방식으로 실행하고 이름을 지정하는 방법
  2. 호스트에서 컨테이너 서비스에 접근하기 위한 포트 매핑
  3. 호스트와 컨테이너 간에 데이터를 공유하기 위한 볼륨 마운트
  4. 컨테이너 설정을 위한 환경 변수 지정
  5. 컨테이너의 리소스 사용량을 제한하는 리소스 제한 적용
  6. 컨테이너 간 통신을 위한 네트워크 설정
  7. 컨테이너의 안정성을 위한 재시작 정책
  8. 컨테이너 시작 시 사용할 작업 디렉터리와 명령 지정

docker run의 이러한 매개변수는 Docker 컨테이너를 설정하고 관리하는 데 유용한 도구입니다. 이 옵션을 익히면 용도에 맞게 더 정교한 컨테이너 배포를 구성할 수 있습니다. 컨테이너가 호스트 시스템과 상호 작용하는 방식, 사용할 수 있는 리소스, 다양한 상황에서의 동작을 제어할 수 있습니다.