Установка ghost с помощью докера

Этот блог работает на движке ghost и я довольно давно его уже не обновлял. Хотя за это время было много серьезных апдейтов. Например, они наконец-то написали нормальную админку на ember.js. К сожалению ребята не заморачиваются с разработкой системы автообновления, поэтому переход на новую версию требует ручной работы.

В этот раз я решил облегчить себе работу по переходу на новые версии в будущем и сделать все стильно, модно, молодежно на docker. Docker - это система контейнерной виртуализации. Он позволяет упаковывать приложения в легковесные контейнеры и затем запускать их в различных средах.

Не буду описывать как установить сам docker, это подробно описано в документации.

Разработчики ghost делают официальный docker образ (image) который можно использовать - https://hub.docker.com/_/ghost/. Благодаря этому все что вам нужно чтобы развернуть свежую версию ghost у себя это выполнить команду:

docker run --name ghost-blog -p 8080:2368 -d ghost  

Это команда запускает новый контейнер с именем ghost-blog на основе образа с именем ghost. Если docker не найдет образ локально, то скачает его с docker хаба. Опция -p делает маппинг портов между хостовой машиной и контейнером. 2368 это порт на котором по дефолту работает ghost.

Теперь можно открыть в браузере http://localhost:8080 и увидеть что блог работает. Но тут есть один нюанс, если вы работаете на линуксе, где docker работает нативно, то адрес будет именно localhost. Но для операционных систем Mac OS X и Windows docker использует виртуальную машину в качестве хостовой. Поэтому вам нужно будет выполнить команду docker-machine ip default и полученный ip-адрес ввести в браузере.

Опция -d нужна чтобы запустить контейнер в detach режиме. Т.е. контейнер будет работать в фоне и не прекратить работу если вы закроете консоль.

Список контейнеров можно увидеть командой docker ps -a. Опция -a показывает все контейнеры, иначе по умолчанию будут показаны только активные.

Но такой способ запуска ghost подходит только для экспериментов, так как при работе он будет сохранять данные внутри контейнера. А это значит что мы их потеряем при удалении контейнера. А удалять контейнеры приходится часто, так как многие опции, типа маппинга портов, нельзя изменить после создания контейнера.

Чтобы хранить данные отдельно от контейнера с приложением можно создать специальный data-контейнер, либо замапить папку с хостовой машины. Воспользуемся вторым способом:

docker run --name ghost-blog -v /home/dev/ekaragodin.com/content:/var/lib/ghost -p 8080:2368 -d ghost  

Не забудьте что перед тем как выполнить эту команду вам сначала нужно остановить и удалить предыдущий контейнер:

docker stop ghost-blog  
docker rm ghost-blog  

Все это здорово, но на реальном сервере я бы хотел чтобы ghost был скрыт за nginx'ом. Для этого понадобится второй контейнер с nginx и docker-compose чтобы облегчить себе работу с приложением состоящем из нескольких контейнеров.

Создадим файл docker-compose.yml со следующим содержанием:

ghost-blog:  
  image: ghost
  volumes:
    - /home/dev/ekaragodin.com/content:/var/lib/ghost
  environment:
    - NODE_ENV=production
nginx:  
  image: nginx
  ports:
    - "80:80"
  volumes:
    - /home/dev/nginx/default.conf:/etc/nginx/nginx.conf
  links:
    - ghost-blog

Создается два контейнера, для каждого указан образ на основе которого он будет создан. Volumes и ports это знакомые нам опции -v и -p из команды run. При этом наружу торчит только порт nginx. Для ghost еще указана переменная окружения чтобы он работал в режиме production.

Для nginx указана опция links. Она нужна чтобы nginx мог проксировать запросы к ghost. При создании контейнера с nginx в его /etc/hosts будет добавлена запись ghost-blog которая будет указывать на ip адрес контейнера с ghost.

Таким образом в конфиге nginx можно ссылаться на ghost по имени хоста:

server {  
    listen   80;

    location / {
       proxy_pass http://ghost-blog:2368;
       proxy_set_header Host $host;
    }
}

С помощью docker-compose я теперь могу управлять этими контейнерами как единым целым, docker-compose up -d и оба контейнера стартуют и работают в фоне.

Теперь когда выйдет новая версия ghost мне нужно будет просто скачать свежий image.