Docker와 NPM을 이용한 개발자/연구자용 개인 웹서버 및 서브 도메인 설정

tl;dr, 하나의 PC, 하나의 ip로 여러개의 서브도메인을 가지는 서비스 이용법.

docker를 이용하여 웹서비스를 설치하는 경우, 예전에 비해 웹서비스를 설치하기 매우 편해진 것은 사실이다.
한 PC에서 하나의 서비스만 제공할 경우 큰 문제없이 설치가 가능하나, 여러 웹서비스를 하나의 PC, 하나의 IP에서 통해 동시에 제공하고자 하는 경우 다음과 같은 몇가지 문제가 발생한다:

  • 80포트를 사용하지 않고 다른 포트를 경유해야 하는데 어떻게 관리해야 할지 막막하다.
  • db를 사용하는 경우 보안에 신경써야 하는데, 서비스마다 SSL을 설치하기가 성가신 편이다.
  • docker hub에서 기본적으로 제공하는 docker-compose.yml을 그대로 사용하기 힘들다.

이런 상황에서 서브 도메인 또는 다른 도메인 주소를 이용하여 다른 서비스를 제공할 수 있다.
구입한 도메인 주소 ( .com, .net, .kr 등) 하나가 있는 상황이라면,

  • 도메인 주소 하나를 사놨으면 서브도메인을 무료로 등록하여 활용할 수 있다.
  • 서브 도메인 등 여러 도메인 주소를 활용하여 각 서비스를 할당할 경우,
    하나의 도메인 주소에서 이상한 방법으로 포트 변경을 시켜 우회할 필요없이 80포트를 사용할 수 있다.

다수의 IP를 확보한 상황이라면 서브 도메인 사용 시 서브도메인 하나 당 하나의 IP를 할당하여 서비스를 계획 할 수도 있겠지만, 특정 기관에 소속된게 아닌 이상, 개인이 다수의 IP를 가지는건 비용 상으로 비효율적이다. 아래에 소개하는 방법으로는 서브 도메인 뿐만 아니라 심지어 본인 소유의 다른 도메인 주소도 하나의 IP로 통합하여 서비스를 제공하는 일도 가능하다.

당연한 얘기겠지만 꽤 큰 자원을 활용하는 일이니 좋은 PC사양을 확보해야 한다.
NPM, Nginx, Gitlab, WordPress 운영 시 12Gb 정도의 메모리가 사용되고 있음.

일주일에 가까운 삽질을 반복하다가 겨우 성공해서 또 다시 삽질이 반복되는 일을 막기 위해 글로 남겨둔다.
적당히 docker와 네트워크에 대한 지식이 있는 사람을 대상으로 최소한의 방향만을 제시한다.

docker network 구성 시 사용했던 docker-compose.yml 을 참고용으로 남겨둔다.
나머지는 검색을 활용하길.

  • OpenSSH 설치: 22번 port 개방
    • SSH / SFTP 사용을 위해 필요.
  • 도메인 등록
    • 업체
      • godaddy, hosting.kr, cafe24, …
    • 서브 도메인 등록: www 포함하여 모두 ip를 가리키는 A레코드로 등록
      • blog.nitrolab.kr
      • git.nitrolab.kr
      • www.nitrolab.kr
    • 하나의 ip로 targeting이 되어있지만 아래 서술할 NPM이 모든 문제를 해결해줌.
    • NPM을 통한 SSL관리를 위해 dns관리를 기존 업체에서 cloudflare로 옮김.
      • cloudflare 가입 후 구입한 주소 제공시 뭘 해야하는지 알려줌
      • cloudflare 로 dns 이전 후 제공하는 proxy는 제거할 것.
  • Docker 설치
    • nitrolab.kr: Nginx Proxy Manager (NPM)
      • https://nginxproxymanager.com/
      • 80/443 port를 통하는 모든 서브 도메인의 서비스를 관리.
        • SSL 자동 설치
        • http -> https 자동 리다이렉트
      • 관리 페이지: 81 port
        • 기본 ID/PW : admin@example.com / changeme
      • 서비스 관리용 db(mysql/mariadb) port: 3306
      • 이후 설치되는 docker는 외부에 오픈되는 port 없이 자체 network bridge를 통해 동작하도록 설정
        • 기본으로 제공되는 docker-compose.yml에서 network 항목에 추가하면 편리.
        • 아래의 예시는 [nitroLab] 이름의 bridge에서 동작하게 설정.
      • 관리 페이지
        • SSL 인증서 획득: nitrolab.kr, *.nitrolab.kr
        • cloudflare에서 인증서 획득을 위한 API 토큰 획득 후 입력
          • Let’s Encrypt를 이용하는 경우 3개월에 한번 인증서를 갱신해주어야 함.
          • 갱신 기한을 놓치는 경우 재앙이 생길수 있다는 정보가 있으므로 주의할 것.
        • 관리페이지를 통해 [add proxy host]로 subdomain 등록.
          • ssl 등록 및 80 port로 설정.
            • 등록 후 해당 페이지는 자동으로 https로 리다이렉트 됨.
          • hostname에 ip나 domain입력이 아닌 docker container name 입력.
          • 참조: https://youtu.be/P3imFC7GSr0
    • www.nitrolab.kr: Nginx
      • 메인 웹서버: 당연히 다른걸 써도 상관은 없음.
      • 웹서버 설치 후 nitrolab.kr:80은 www.nitrolab.kr로 redirect되도록 nitrolab.kr:81에서 설정
      • docker 내부의 /etc/nginx/conf.d/nginx.conf 설정
        • 유입가능한 server_name 조정: nitrolab.kr www.nitrolab.kr
        • 주석 해제를 통한 log파일 설정
      • goaccess 설치를 통해 유입 통계 확인
      • docker에는 제일 기본적인 것만 깔려있으므로 아래의 명령어를 활용한다
        • apt-get update
        • apt-get install vim goaccess
    • git.nitrolab.kr: GitLab CE
      • 메모리를 5Gb 이상으로 상당한 리소스를 잡아먹음
      • 80/443 port는 NPM에서 관리하므로 기본 제공 docker-compose.yml 에서 노출되는 포트는 22번만 변경해서 남기고 나머지는 모두 제거.
      • external url 관련 GITLAB_OMNIBUS_CONFIG 작성.
    • blog.nitrolab.kr: WordPress
      • wordpress + mysql docker 사용
      • WordPress 에서 공식적으로 제공하는 docker-compose.yml은 mysql container의 포트가 명시되지 않아 default값인 3306으로 설정되어, NPM의 mysql 포트와 충돌되니 주의.
      • docker-compose에서 db container측 environment에 MYSQL_TCP_PORT: 3307 항목을 추가하고, wordpress에 해당 포트를 연결.
      • 설치에 실패할 경우 생성된 volume을 모두 삭제하고 재설치해야 함.
  • docker network 내부 확인 command
    • docker network ls
    • docker network inspect nitroLab
version: "3"
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: npm
    restart: always
    ports:
      - '80:80'
      - '443:443'
      - '81:81'
    environment:
      # These are the settings to access your db
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: "npm"
      DB_MYSQL_NAME: "npm"
      # If you would rather use Sqlite uncomment this
      # and remove all DB_MYSQL_* lines above
      # DB_SQLITE_FILE: "/data/database.sqlite"
      # Uncomment this if IPv6 is not enabled on your host
      # DISABLE_IPV6: 'true'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    depends_on:
      - db
  db:
    image: 'jc21/mariadb-aria:latest'
    container_name: npm_db
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 'npm'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm'
    volumes:
      - ./data/mysql:/var/lib/mysql
networks:
  default:
    name: nitroLab
version: '3.4'
services:
  web:
    image: "gitlab/gitlab-ce:latest"
    container_name: git_nitroLab
    restart: always
    hostname: "git.nitrolab.kr"
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://git.nitrolab.kr'
        registry_external_url 'https://git.nitrolab.kr'
        gitlab_rails['registry_enabled']=true
        gitlab_rails['registry_host']='git.nitrolab.kr'
        nginx['listen_port'] = 80
        nginx['listen_https'] = false
        registry_nginx['listen_port'] = 80
        registry_nginx['listen_https'] = false
        gitlab_rails['gitlab_shell_ssh_port'] = XX22 # no 22
    ports:
      - "XX22:22" # no 22
    volumes:
      - "gitlab_path/config:/etc/gitlab"
      - "gitlab_path/logs:/var/log/gitlab"
      - "gitlab_path/data:/var/opt/gitlab"
networks:
  default:
    name: nitroLab
version: "3.9"

services:
  db_wordpress:
    image: mysql:5.7
    container_name: mysql-db
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_TCP_PORT: XXXX # no 3306
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: NitroLab
      MYSQL_USER: mysqluser
      MYSQL_PASSWORD: password
  wordpress:
    depends_on:
      - db_wordpress
    image: wordpress:latest
    container_name: wordpress-blog
    volumes:
      - wordpress_data:/var/www/html
    ports:
      - "XX80:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db_wordpress:XXXX # no 3306
      WORDPRESS_DB_USER: mysqluser
      WORDPRESS_DB_PASSWORD: password
      WORDPRESS_DB_NAME: NitroLab
volumes:
  db_data: {}
  wordpress_data: {}
networks:
  default:
    name: nitroLab
Avatar photo

Dr. Nitro

저에게 시간과 예산이 좀 더 있었더라면 . . .

You may also like...

1 Response

  1. 2022년 05월 25일

    […] NPM 사용시 https 대신 http로 설정 (https로 redirect됨) […]

Leave a Reply

Your email address will not be published.