Docker 관리 · 10 min read · Sep 22, 2025

Docker 관리를 위한 Portainer 설치 및 사용 방법 (Nginx Proxy Manager 포함)

Portainer는 Docker, Kubernetes 및 Nomad를 위한 오픈 소스 컨테이너 관리 솔루션으로, 컨테이너를 쉽게 시작하고 생성하며 실행할 수 있도록 간소화합니다. 컨테이너, 이미지, 네트워크 및 볼륨을 관리하기 위한 웹 기반 대시보드를 제공합니다.

이 튜토리얼에서는 Linux 서버에 Portainer 컨테이너 관리 솔루션을 설치하고 구성하는 방법과 이를 사용하여 다양한 앱을 실행하기 위한 Docker 컨테이너를 생성하고 관리하는 방법을 배웁니다. 또한 Nginx 프록시 관리자를 사용하여 이러한 컨테이너를 Nginx 뒤에 배치하는 방법도 배웁니다.

필수 조건

  • Ubuntu / Debian / Cent OS / Rocky Linux 8 / Alma Linux를 실행하는 Linux 서버.
  • sudo 권한이 있는 비루트 사용자.
  • Portainer(portrainer.example.com) 및 Nginx Proxy Manager(npm.example.com)를 위한 서버를 가리키는 완전한 도메인 이름(FQDN).

1단계 - 방화벽 구성

Cent OS/Rocky Linux/Alma Linux

Firewalld 방화벽이 설치되어 있어야 합니다. 방화벽의 상태를 확인합니다.

$ sudo firewall-cmd --state
running

포트 80, 9443 및 443을 엽니다. Portainer는 HTTPS를 통해 웹 UI를 노출하기 위해 포트 9443을 사용합니다. Nginx Proxy Manager는 UI를 위해 포트 81을 사용합니다.

$ sudo firewall-cmd --permanent --add-service=http
$ sudo firewall-cmd --permanent --add-service=https
$ sudo firewall-cmd --permanent --add-port=9443/tcp
$ sudo firewall-cmd --permanent --add-port=81/tcp

변경 사항을 적용하기 위해 방화벽을 다시 로드합니다.

$ sudo firewall-cmd --reload

Ubuntu/Debian

Ubuntu 및 Debian 시스템은 기본적으로 ufw(간단한 방화벽)를 사용합니다.

방화벽이 실행 중인지 확인합니다.

$ sudo ufw status

실행 중이라면 포트 80, 9443 및 443을 엽니다.

$ sudo ufw allow 80
$ sudo ufw allow 443
$ sudo ufw allow 9443
$ sudo ufw allow 81

방화벽이 실행 중이지 않다면 SSH 포트를 엽니다.

$ sudo ufw allow "OpenSSH"

방화벽이 실행 중이지 않다면 방화벽을 활성화합니다.

$ sudo ufw enable

실행 중이라면 변경 사항을 적용하기 위해 다시 로드합니다.

$ sudo ufw reload

2단계 - Docker 설치

Cent OS/Rocky Linux/Alma Linux

다음 명령을 실행하여 Docker를 설치합니다.

$ sudo yum install -y yum-utils
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce docker-ce-cli containerd.io

Ubuntu

$ sudo apt install ca-certificates curl gnupg lsb-release
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io

Debian

$ sudo apt install ca-certificates curl gnupg lsb-release
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io

Docker 서비스를 활성화하고 시작합니다.

$ sudo systemctl start docker --now

사용자를 Docker 그룹에 추가합니다.

$ sudo usermod -aG docker $USER

시스템에서 로그아웃한 후 다시 로그인하여 변경 사항을 적용합니다.

3단계 - Docker Compose 설치

Docker compose 바이너리를 다운로드하고 설치합니다.

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

바이너리에 실행 권한을 부여합니다.

$ sudo chmod +x /usr/local/bin/docker-compose

4단계 - Portainer 설치

Portainer를 위한 디렉토리를 생성합니다.

$ mkdir ~/portainer

디렉토리로 이동합니다.

$ cd ~/portainer

편집을 위해 Docker Compose 파일을 생성하고 엽니다.

$ nano docker-compose.yaml

다음 코드를 붙여넣습니다.

version: "3.3"
services:
    portainer:
      image: portainer/portainer-ce:latest
      container_name: portainer
      restart: always
      privileged: true
      volumes:
        - ./data:/data:Z
        - /var/run/docker.sock:/var/run/docker.sock:Z
      ports:
        - 9443:9443

Ctrl + X를 눌러 파일을 저장하고, 프롬프트가 나타나면 Y를 입력합니다.

Docker compose 파일을 살펴보겠습니다.

  • 우리는 Docker Hub에서 Portainer Community Edition의 최신 버전을 가져오고 있습니다. Portainer Community Edition은 무료로 사용할 수 있으며, 비즈니스 에디션은 유료 라이센스가 필요합니다. 비즈니스 에디션을 가져올 수 있지만 사용하려면 라이센스 키를 요청받게 됩니다.
  • 우리는 식별 및 연결 목적을 위해 컨테이너 이름을 portainer로 지정했습니다.
  • 재시작 정책은 항상으로 설정되어 있어 부팅 중에 컨테이너가 계속 실행됩니다.
  • privileged: true 설정은 Portainer가 Docker 소켓에 접근하고 특권 컨텍스트에서 실행할 수 있도록 하기 위한 것입니다. SELinux를 사용하고 있다면 이 설정을 유지해야 합니다. SELinux를 사용하지 않는 경우 이 설정을 제거할 수 있습니다. 이 설정은 Portainer 컨테이너가 호스트 시스템의 모든 것에 접근할 수 있도록 하며, 하드웨어에 대한 접근도 포함됩니다. 따라서 이 설정을 사용할 때는 주의해야 합니다.
  • volumes 섹션은 호스트의 폴더를 컨테이너의 폴더에 바인드 마운트를 사용하여 매핑합니다. 우리는 관련 데이터를 저장하기 위해 ~/portainer/data 디렉토리를 컨테이너에 노출시켰으며, 컨테이너 관리를 위한 Docker 소켓 API도 포함됩니다. :Z 레이블은 호스트에서 SELinux를 실행하고 있음을 Docker에 알립니다. SELinux가 활성화되어 있지 않다면 이 레이블을 제거해야 합니다.

Portainer를 시작합니다.

$ docker-compose up -d

컨테이너의 상태를 확인합니다.

$ docker ps
CONTAINER ID   IMAGE                           COMMAND        CREATED         STATUS         PORTS                                                           NAMES
916411e8d12e   portainer/portainer-ce:latest   "/portainer"   5 seconds ago   Up 4 seconds   8000/tcp, 9000/tcp, 0.0.0.0:9443->9443/tcp, :::9443->9443/tcp   portainer

5단계 - Portainer에 접근하고 구성하기

브라우저에서 URL https://:9443를 열면 다음 화면이 표시됩니다.

Portainer 설치 화면

새 관리자 사용자를 생성하라는 메시지가 표시됩니다. 사용자 세부 정보를 추가합니다. 개인 정보 보호가 중요하다면 익명 통계 수집 허용 옵션의 체크를 해제합니다. 사용자 생성 버튼을 클릭하여 설치를 시작하고 새 관리자 계정을 생성합니다.

다음으로 다음 대시보드 화면으로 이동합니다.

Portainer 대시보드

몇 초 후 자동으로 새로 고쳐지며 다음 화면이 표시됩니다.

Portainer 홈

Portainer가 실행되고 있는 로컬 환경이 표시됩니다. 로컬 환경을 클릭하여 시작합니다.

Portainer 환경 홈페이지

대부분의 섹션은 자명합니다. 스택 섹션은 Docker compose 파일을 사용하여 컨테이너를 생성하는 데 도움이 됩니다. 사이드바의 컨테이너 카테고리를 사용하여 컨테이너를 직접 배포할 수 있습니다. 호스트 섹션을 통해 현재 Docker 환경을 구성할 수 있습니다. 앱 템플릿 섹션은 가장 일반적인 애플리케이션을 설치하기 위한 사전 설치된 Docker compose 파일을 제공합니다. 사용자 정의 템플릿도 생성할 수 있습니다.

설정 섹션에서는 사용자 접근 구성, 데이터 백업, Portainer 사용자 정의 등 다양한 설정을 구성할 수 있습니다.

5단계 - Nginx Proxy Manager(NPM)를 사용하여 Portainer를 리버스 프록시 뒤에 배치하기

앞으로 나아가기 전에 Nginx Proxy Manager를 사용하여 Portainer를 리버스 프록시 뒤에 배치해 보겠습니다. Nginx Proxy Manager는 Nginx를 리버스 프록시 호스트로 설정하기 위한 웹 관리 UI를 제공하는 Docker 애플리케이션입니다. 또한 리디렉션 또는 스트리밍 호스트로도 사용할 수 있습니다.

NPM 설치

첫 번째 단계는 Nginx Proxy Manager(NPM)를 위한 네트워크를 생성하는 것입니다. 네트워크 섹션을 열고 네트워크 추가 버튼을 클릭하여 새 네트워크를 생성합니다.

Portainer 네트워크 목록

네트워크에 이름을 지정하고 모든 설정을 변경하지 않은 채로 두십시오. 네트워크 생성 버튼을 클릭하여 완료합니다.

Portainer 네트워크 생성 페이지

스택을 방문하고 스택 추가 버튼을 사용하여 새 스택을 생성합니다.

Portainer 스택 페이지

스택 이름을 nginx-proxy-manager로 지정하고 다음 코드를 붙여넣습니다.

version: "3.3"
services:
  npm-app:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: npm-app
    restart: unless-stopped
    ports:
      - '80:80' # 공용 HTTP 포트
      - '443:443' # 공용 HTTPS 포트
      - '81:81' # 관리자 웹 포트
      # 노출할 다른 스트림 포트를 추가하세요
      # - '21:21' # FTP
    environment:
      DB_MYSQL_HOST: "npm-db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: ${DB_MYSQL_PASSWORD}
      DB_MYSQL_NAME: "npm"
      # 호스트에서 IPv6가 활성화되어 있지 않은 경우 아래 줄의 주석을 제거하세요
      # DISABLE_IPV6: 'true'
    volumes:
      - ./npm-data:/data:Z
      - ./letsencrypt:/etc/letsencrypt:Z
    depends_on:
      - npm-db
    networks:
      - npm-network
      - npm-internal

  npm-db:
    image: 'mariadb:latest'
    container_name: npm-db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: ${DB_MYSQL_PASSWORD}
    volumes:
      - ./npm-data/mysql:/var/lib/mysql:Z
    networks:
      - npm-internal

networks:
  npm-internal:
  npm-network:
    external: true

Portainer 스택 추가 페이지

우리는 데이터베이스 및 루트 MySQL 비밀번호를 설정하기 위해 두 개의 환경 변수를 설정했습니다. Portainer는 환경 변수를 사용하여 비밀을 설정하는 데 사용할 수 있습니다. 페이지를 아래로 스크롤하고 환경 변수 추가 버튼을 클릭하여 강력한 비밀번호를 추가합니다.

Portainer 스택 환경 변수

스택 배포 버튼을 클릭하여 NPM 컨테이너를 생성하고 시작합니다.

NPM 접근

브라우저에서 URL https://:81을 열면 다음 화면이 표시됩니다. 다음 기본 자격 증명을 입력하여 로그인합니다.

이메일 주소: [email protected] 비밀번호: changeme

다음으로 즉시 이름과 이메일 주소를 설정하라는 메시지가 표시됩니다. 저장 버튼을 클릭하고 새 비밀번호를 생성하라는 메시지가 표시됩니다. 저장 버튼을 다시 클릭하여 시작합니다.

Nginx Proxy Manager 대시보드

호스트 >> 프록시 호스트로 이동하고 프록시 호스트 추가 버튼을 클릭합니다.

Portainer를 프록시 호스트로 추가

도메인 이름을 portainer.example.com으로 입력합니다. 스킴을 https로 선택합니다. 전달 호스트 이름으로 컨테이너 이름을 입력하고 전달 포트로 9443을 입력합니다. 일반적인 공격 차단웹소켓 지원 옵션을 체크합니다.

Portainer NPM SSL 옵션

SSL 탭으로 전환하고 드롭다운 메뉴에서 새 SSL 인증서 요청을 선택합니다. SSL 강제 적용HTTP/2 지원 옵션을 체크하여 SSL 연결을 안전하게 하고 최적화합니다. 갱신 알림을 받을 이메일 주소를 입력하고 서비스 약관에 동의합니다. 저장 버튼을 클릭하여 Portainer의 프록시 호스트 설정을 완료합니다.

Portainer를 NPM 컨테이너에 연결

프록시 호스트를 설정했지만 컨테이너는 여전히 NPM 네트워크에 연결되어 있지 않습니다. Portainer 대시보드로 돌아가서 컨테이너 섹션을 방문하고 portainer 컨테이너를 선택합니다.

연결된 네트워크 섹션의 드롭다운 메뉴에서 npm-network를 선택하고 네트워크에 가입 버튼을 클릭하여 Portainer 컨테이너를 프록시 관리자의 네트워크에 추가합니다.

Portainer 연결된 네트워크

오류가 발생할 수 있지만 페이지를 새로 고치면 컨테이너가 NPM 네트워크에 추가된 것을 볼 수 있습니다.

Portainer가 NPM에 연결됨

브라우저에서 URL https://portainer.example.com을 사용하여 Portainer에 접근할 수 있어야 합니다.

NPM을 https://npm.example.com과 같은 공개적으로 접근 가능한 URL 뒤에 배치하는 유사한 절차를 따를 수 있습니다. 이는 우리의 Nginx Proxy Manager 튜토리얼에서 논의되었습니다.

이제 Portainer에 대한 공개 URL을 설정했으므로 노출된 9443 포트를 제거할 수 있습니다. 이를 위해 터미널로 돌아가서 portainer 디렉토리로 이동합니다.

$ cd ~/portainer

편집을 위해 Docker compose 파일을 엽니다.

$ nano docker-compose.yaml

포트 섹션을 주석 처리하여 제거합니다. 아래와 같이 표시됩니다.

version: "3.3"
services:
    portainer:
      image: portainer/portainer-ce:latest
      container_name: portainer
      restart: always
      privileged: true
      volumes:
        - ./data:/data:Z
        - /var/run/docker.sock:/var/run/docker.sock:Z
      #ports:
      #  - 9443:9443
      networks:
        - npm-network

networks:
  npm-network:
    external: true

Ctrl + X를 눌러 파일을 저장하고, 프롬프트가 나타나면 Y를 입력합니다.

여기서는 NPM 네트워크의 세부 정보를 추가했으며, Portainer 컨테이너를 재시작해야 합니다.

Portainer 컨테이너를 중지합니다.

$ docker-compose down --remove-orphans

업데이트된 구성으로 컨테이너를 다시 시작합니다.

$ docker-compose up -d

6단계 - 앱 템플릿을 사용하여 컨테이너 배포

Portainer는 최소한의 구성으로 애플리케이션을 직접 시작하기 위한 여러 사전 정의된 템플릿을 제공합니다.

Portainer 앱 템플릿

앱 템플릿 섹션을 방문하고 원하는 템플릿을 선택합니다. 이름을 지정하고 사용할 네트워크를 선택합니다. 고급 옵션 섹션을 사용하여 사용자 정의 포트, 네트워크 및 볼륨 마운트를 배포합니다.

컨테이너 배포 버튼을 클릭하여 애플리케이션 배포를 완료합니다. 여기서는 Redis 컨테이너를 배포하고 있습니다.

Portainer Redis 앱 배포

7단계 - 컨테이너 관리

기존 컨테이너를 관리해 보겠습니다. 컨테이너 페이지를 열면 실행 중인 모든 컨테이너가 표시됩니다.

Portainer 컨테이너 목록

최근에 생성된 hw-redis 컨테이너를 클릭하여 진행합니다.

Portainer 컨테이너 작업

상단에는 실행 중인 컨테이너에서 수행할 수 있는 작업 목록이 표시됩니다. 컨테이너를 중지하고 종료할 수 있습니다. 재생성은 컨테이너를 처음부터 생성합니다. 복제/편집 옵션을 사용하면 동일한 컨테이너를 생성할 수 있으며, 시작하기 전에 설정을 변경할 수 있습니다.

컨테이너 상태는 실행 시간, IP 주소 및 컨테이너에 대한 기타 세부 정보를 표시합니다.

로그 옵션은 docker logs 명령의 출력을 보여줍니다. 명령의 출력은 캐시되지 않으므로 페이지를 새로 고칠 때마다 명령이 처음부터 실행됩니다.

Portainer 컨테이너 로그

검사 옵션은 컨테이너에서 docker inspect 명령을 실행하고 출력을 보여줍니다.

Portainer 컨테이너 검사

통계 옵션은 실시간으로 컨테이너의 사용량을 보여줍니다.

Portainer 컨테이너 통계

콘솔 옵션을 사용하여 컨테이너 콘솔을 실행할 수 있습니다. 명령과 실행할 시스템 사용자를 요청받습니다.

Portainer 컨테이너 콘솔 구성

연결 버튼을 눌러 콘솔을 실행합니다.

Portainer 컨테이너 콘솔 셸

첨부 옵션은 docker attach 명령을 실행합니다.

컨테이너 세부 정보 페이지에는 다른 옵션이 있습니다. 기존 컨테이너를 사용하여 이미지를 생성할 수 있습니다. 다른 옵션으로는 컨테이너의 재시작 정책을 변경하거나 기존 컨테이너에 네트워크를 연결하거나 연결을 끊는 것이 있습니다.

Portainer에 외부 컨테이너 연결

Portainer 외부에서 생성된 모든 컨테이너는 Portainer가 실행되고 있는 동일한 시스템에서 생성된 경우 내부에 표시됩니다. 이는 Portainer가 웹소켓을 사용하여 Docker와 연결되어 있기 때문에 가능합니다.

Hello World Docker 컨테이너를 실행하여 테스트해 보겠습니다.

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:10d7d58d5ebd2a652f4d93fdd86da8f265f5318c6a73cc5b6a9798ff6d2b2e67
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

터미널에서 컨테이너 목록을 확인합니다. -a 플래그를 사용하여 중지된 컨테이너를 포함한 모든 컨테이너 목록을 표시합니다. 컨테이너 이름이 sad_williamson으로 표시됩니다.

$ docker ps -a
CONTAINER ID   IMAGE                             COMMAND                  CREATED         STATUS                     PORTS                                                                                  NAMES
5fa46b85d594   hello-world                       "/hello"                 3 minutes ago   Exited (0) 3 minutes ago                                                                                          sad_williamson
.....

이제 Portainer 컨테이너 페이지를 확인하면 hello world 컨테이너가 중지된 상태로 목록에 표시됩니다.

Portainer Hello World 컨테이너

결론

이로써 Docker 관리 및 Nginx Proxy Manager를 위한 Portainer 설치 및 사용에 대한 튜토리얼이 마무리되었습니다. 다음 튜토리얼에서는 Docker 이미지 빌드, 사용자 정의 컨테이너 생성 및 Docker swarm과 함께 Portainer 사용에 대해 탐구할 것입니다. 질문이 있으시면 아래 댓글에 남겨주세요.

Share: X/Twitter LinkedIn

새 게시물을 받은 편지함에서 받기

스팸은 없습니다. 언제든지 구독 해지 가능합니다.