4월 11, 2019 · developemnt

Init - Ghost and Nginx within Docker using Amazon Lightsail

블로그 시작 - 아마존 Lightsail에서 도커를 통한 nginx와 ghost 사용기

개발 블로그에 대한 필요성을 느끼기 시작한 것은 오래전이다. 하지만, 이런 저런 이유로 막상 시작하지 못(안) 했다. 그러나 올해부터 생활 환경의 변화를 맞이하면서 블로그도 함께 시작하기로 하였다. 어떤 블로그 서비스를 사용할 지 고민한 중 ghost를 사용하기로 결정했다. 마침 Docker의 공부도 할 필요성을 느꼈기 때문에 ghost와 nginx를 docker에 올려서 사용해 봄으로써 공부도 하고 블로깅도 시작할 수 있는 기회가 되었으면 하였다.

Lightsail 인스턴스 만들기

서버는 AWS의 Lightsail을 사용했다. 기존에 개인적으로 ec2를 잠깐 사용해본 적 있으나 ec2보다 좀 더 간편하게 할 수 있다고 한 Lightsail로 서버를 호스팅하기로 결정했다. Lightsail에서 인스턴스를 생성하는 법은 정말 간단했다. ec2에서 인스턴스를 올리기 위해서 할 수 있는 설정에 비하면 Lightsail에서 할 수 있는 설정의 수는 적다. 간단히 인스턴스를 올리는 것이 목적이라면 Lightsail이 좀 더 편리한 선택이 될 것이다.

ec2의 인스턴스 생성 창

블로그를 위해 도쿄 리전의 Ubuntu 18.04 LTS인스턴스를 선택하였다. 클릭을 통해 다음과 같이 간단히 설정할 수 있다.

Lightsail 인스턴스의 리전과 블루프린트 설정

다음으로 사용할 플랜을 고르면 더이상 할 것이 없다. 플랜만 고르면 사용한 프로세서, 메모리, 스토리지, 그리고 네트워크 량 까지 묶어서 제공받는다.

이 것 만으로도 인스턴스를 받을 수 있지만, 나는 추가적으로 SSH key pair를 다른것으로 등록시켰다. Lightsail에서는 dbms 시스템, 추가적인 스토리지 디스크, 스냅샷 그리고 정적 IP 까지 지원한다. 가동중인 인스턴스가 있다면 그 인스턴스에 묶여있는 정적 IP의 유지비는 내지 않아도 된다. 이제 인스턴스를 손에 얻었으니 ssh를 사용해 인스턴스에 접속할 수 있다.

Docker 설치 및 docker-compose

Docker와 Docker-compose가 무엇인지 그리고 어떻게 설치할 수 있는지에 대한 훌륭한 (한국어) 글들(블로그글, 한국어 docker 문서 집합)이 인터넷에 많아서 참고로 진행하기 쉬웠다. ghost로 블로그를 호스팅하기 위해 다음과 같은 docker-compose를 작성했다.

version: '3'

services:
    nginx:
        container_name: nginx
        image: nginx
        ports:
            - 80:80
            - 443:443
        volumes:
            - ./nginx/conf.d:/etc/nginx/conf.d
            - ./nginx/ssl:/etc/ssl
        links:
            - ghost:ghost

    ghost:
        container_name: ghost
        image: ghost
        volumes:
            - ./ghost/content:/var/lib/ghost/content
            - ./ghost/config.production.json:\
                        /var/lib/ghost/config.production.json
        environment:
            - NODE_ENV=production

nginx를 사용해서 리버스 프록시를 통해 ghost의 서비스에 접속할 수 있게 하였다. MySQL을 추가로 사용하여 ghost가 db로 사용할 수 있도록 하고 싶었으나, 내가 선택한 Lightsail 플랜의 메모리 크기 (1GB)를 고려하여 사용하지 않았다. 이제 docker-compose를 사용해서 컨테이너를 한번에 올리거나, 실행 및 정지 시킬 수 있다.

처음에는 networks를 통해 네트워크를 명시적으로 지정하고, 각 컨테이너를 네트워크에 포함시키는 것을 통해 nginx가 ghost를 볼 수 있게 하고 싶었으나 잘 되지 않아서 명시적으로 links를 사용하여 볼 수 있도록 하였다.

Nginx 및 Ghost 설정

Docker-compose 설정에서 볼 수 있듯이, 설정 파일을 통해 각각 nginx와 ghost를 설정하였다. ghost의 경우 설정파일을 이용하지 않고 환경변수를 통해 설정할 수도 있다. Nginx의 기본 설정 파일을 보면 다음과 같은 사실을 알 수 있다.

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

맨 아래 줄을 보면 자동으로 conf.d/의 모든 conf파일을 포함하고 있다. 따라서, (컨테이너 내부에 있는) 이 폴더를 호스트와 연동시켜 호스트에서 설정한 conf 파일을 사용하게 하였다. Nginx 설정 파일에서 80포트로 들어온 http를 https로 리다이렉트 해주고, 433포트로 들어온 https에서 ssl 설정과 ghost로의 리버스 프록시를 진행하였다. 사용한 conf 파일들은 다음과 같다.

ghost의 컨테이너를 설정할 때 환경변수로 NODE_ENV =  production으로 설정하여 config.production.json을 읽도록 설정하였다. 그래야만 ghost가 올바른 설정파일을 읽는다. ghost 설정 파일 내부에는 url정보와 sqlite3를 위한 정보 등을 설정할 수 있다. 그 외 이미지 압축을 할 것인지 여부도 나는 false로 설정하였다. 공식 문서에 어떤 설정을 할 수 있는지 나와있어 참고하면서 진행했다. 내가 사용한 설정 json파일은 다음과 같다.

{
    "url": "https://elenesgu.dev",
    "server": {
        "host": "0.0.0.0",
        "port": 2368
    },
    "mail": {
        "service": "Gmail",
        "transport": "SMTP",
        "options": {
            "host": "smtp.gmail.com",
            "port": "465",
            "secureConnection": true
        }
    },
    "database": {
        "client": "sqlite3",
        "connection": {
            "filename": "/var/lib/ghost/content/data/ghost.db"
        }
    },
    "paths": {
        "contentPath": "/var/lib/ghost/content/"
    },
    "imageOptimization": {
        "resize": false
    }
}

설정 이후

지금 보고 있는 이 블로그는 위와 같은 과정 및 설정을 통해 탄생하였다. 스스로 웹 서비스를 호스팅한 경험이 없어서 새롭기도 하여 재밌게 진행할 수 있었다. 처음 SSL Lab 에서 이 블로그 사이트를 검증했을 때는, B등급으로 책정되었고 이를 해결하기 위해 검색을 통해 nginx 설정을 수정하는 과정을 걸쳤다. 아직 A+는 아니지만 차후 공부해 나가면서 수정해 나갈것이 기대된다.

도메인

이글의 개발 과정이 현재 도메인 (elenesgu.dev)에서 이루어진 것이 아니다. 지인의 도메인을 빌려 블로그를 구축하였고, 그 이후 도메인을 구입하였다. Google Domain에 구입하였으며 (서브 도메인을 포함하여) 다양한 설정이 있었으나, 나는 도메인 -> IP의 포워딩만 설정해 둔 상태다.