Этот блог работает на движке 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.