Cómo instalar Ghost CMS con Docker en Ubuntu 20.04
Ghost es una plataforma de blogs de código abierto que te ayuda a crear un blog de aspecto profesional. Se lanzó en 2013 como alternativa a WordPress porque se estaba volviendo demasiado complejo. Ghost está escrito en JavaScript y funciona con Node.js.
En este tutorial, exploraremos cómo instalar Ghost CMS utilizando Docker en un servidor con Ubuntu 20.04. También utilizaremos Nginx como proxy y el certificado SSL Let’s Encrypt para asegurar nuestra instalación.
Requisitos previos
-
Un servidor con Ubuntu 20.04.
-
Un usuario sudo no root.
-
Asegúrate de que todo está actualizado.
$ sudo apt update $ sudo apt upgrade
Paso 1 - Configurar el cortafuegos UFW
El primer paso es configurar el cortafuegos. Ubuntu viene con ufw (Uncomplicated Firewall) por defecto.
Comprueba si el cortafuegos se está ejecutando.
$ sudo ufw status
Deberías obtener la siguiente salida.
Status: inactive
Permite el puerto SSH para que el cortafuegos no rompa la conexión actual al activarlo.
$ sudo ufw allow OpenSSH
Permite también los puertos HTTP y HTTPS.
$ sudo ufw allow 80
$ sudo ufw allow 443
Habilita el cortafuegos
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
Comprueba de nuevo el estado del cortafuegos.
$ sudo ufw status
Deberías ver una salida similar.
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80 ALLOW Anywhere
443 ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
80 (v6) ALLOW Anywhere (v6)
443 (v6) ALLOW Anywhere (v6)
Paso 2 - Instalar Certbot y obtener el certificado SSL
Antes de continuar, necesitamos instalar la herramienta Certbot e instalar un certificado SSL para nuestro dominio.
Para instalar Certbot, utilizaremos el instalador de paquetes Snapd. El repositorio oficial de Certbot ha quedado obsoleto y el paquete Certbot de Ubuntu tiene más de un año de antigüedad. Snapd siempre lleva la última versión estable de Certbot y deberías usarla. Afortunadamente, Ubuntu 20.04 viene con Snapd preinstalado.
Asegúrate de que tu versión de Snapd está actualizada.
$ sudo snap install core
$ sudo snap refresh core
Elimina cualquier versión antigua de Certbot.
$ sudo apt remove certbot
Instala Certbot.
$ sudo snap install --classic certbot
Utiliza el siguiente comando para asegurarte de que el comando Certbot puede ejecutarse creando un enlace simbólico al directorio /usr/bin
.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Genera un certificado SSL.
$ sudo certbot certonly --standalone -d example.com
El comando anterior descargará un certificado en el directorio /etc/letsencrypt/live/example.com
de tu servidor.
Paso 3 - Instalar Docker y Docker Compose
El primer paso es instalar el motor Docker y Docker Compose. Primero, desinstala cualquier versión antigua de Docker.
$ sudo apt remove docker docker-engine docker.io containerd runc
Instala algunos paquetes necesarios para que Docker funcione.
$ sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release
Añade la clave GPG oficial de Docker.
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
Añade el repositorio oficial de Docker.
$ echo "deb [arch=amd64 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
Actualiza los repositorios del sistema.
$ sudo apt update
Instala la última versión de Docker Engine.
$ sudo apt install docker-ce docker-ce-cli containerd.io
Comprueba que Docker Engine se está ejecutando e instalando correctamente.
$ sudo docker run hello-world
Por defecto, Docker requiere sudo para ejecutarse. Para evitarlo, podemos añadir la cuenta de usuario actual al grupo de usuarios docker
.
$ sudo usermod -aG docker ${USER}
Para aplicar la nueva pertenencia al grupo, cierra la sesión y vuelve a iniciarla o utiliza el siguiente comando.
$ su - ${USER}
Ahora, puedes ejecutar los comandos de Docker sin usar sudo.
A continuación, descarga la versión estable actual de Docker compose.
sudo curl -L "https://github.com/docker/compose/releases/download/1.28.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
En el momento de escribir este tutorial, 1.28.6 es la última versión de Docker compose. Siempre puedes cambiar o elegir una versión diferente en el comando consultando desde la página de versiones de Github de Docker compose.
Aplica el permiso de ejecución a la versión instalada de Docker compose.
$ sudo chmod +x /usr/local/bin/docker-compose
Prueba la instalación.
$ docker-compose --version
docker-compose version 1.28.6, build 5db8d86f
Paso 4 - Instalar Ghost
La instalación de Ghost constará de tres componentes: el paquete Ghost, un servidor de bases de datos como MySQL y un servidor web (Nginx). Todos estos servicios pueden instalarse utilizando un único archivo Docker compose.
Crear un archivo Docker Compose
En primer lugar, crea un directorio para almacenar y lanzar tu archivo Docker Compose.
$ mkdir ghost && cd ghost
Crea un archivo llamado docker-compose.yml
y ábrelo con el editor Nano.
$ nano docker-compose.yml
Pega el siguiente código en el archivo. Sustituye example.com
por tu dominio e inserta una contraseña de base de datos en lugar del valor your_password
. Mantén los valores de database__connection__password
y MYSQL_ROOT_PASSWORD
iguales. Sustituye <username>
por el nombre de usuario de tu servidor.
version: '3.3'
services:
ghost:
image: ghost:latest
restart: always
depends_on:
- db
environment:
url: https://example.com
database__client: mysql
database__connection__host: db
database__connection__user: ghost
database__connection__password: ghostdbpass
database__connection__database: ghostdb
mail__transport: SMTP
mail__options__host: {Your Mail Service host}
mail__options__port: {Your Mail Service port}
mail__options__secureConnection: {true/false}
mail__options__service: {Your Mail Service}
mail__options__auth__user: {Your User Name}
mail__options__auth__pass: {Your Password}
volumes:
- /home/<username>/ghost/content:/var/lib/ghost/content
db:
image: mariadb:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: your_mysql_root_password
MYSQL_USER: ghost
MYSQL_PASSWORD: ghostdbpass
MYSQL_DATABASE: ghostdb
volumes:
- /home/<username>/ghost/mysql:/var/lib/mysql
nginx:
build:
context: ./nginx
dockerfile: Dockerfile
restart: always
depends_on:
- ghost
ports:
- "80:80"
- "443:443"
volumes:
- /etc/letsencrypt/:/etc/letsencrypt/
- /usr/share/nginx/html:/usr/share/nginx/html
El archivo Docker compose crea unos puntos de montaje, es decir, mapea ciertos directorios del servidor a directorios dentro del contenedor.
- Los directorios
/var/lib/ghost/content
y/var/lib/mysql
dentro de tus contenedores se asignan a/home/<username>/ghost/content
y/home/<username>/ghost/mysql
en el servidor. - Nginx utiliza el enlace
/etc/letsencrypt/
para acceder a los certificados de Let's Encrypt desde el servidor. - Nginx también necesita acceder al directorio de usuario
/usr/share/nginx/html
para poder acceder a los archivos de Let's Encrypt Challenge del certificado.
En el archivo anterior, también hemos incluido opciones para configurar el correo. Si utilizas un servicio de correo SMTP popular como Mailgun, Mailjet, Mandrill, Postmark, Sendgrid, SendCloud, SES, Zoho o Gmail, puedes añadir simplemente el nombre del servicio y tu nombre de usuario y contraseña SMTP y prescindir del resto de los campos. Si no, rellena todas las demás opciones y elimina el nombre del servicio y debería seguir funcionando. Puedes consultar más opciones de correo en la documentación de Ghost sobre Opciones de correo.
Crea directorios para todos los montajes de bind descritos anteriormente (excepto para /etc/letsencrypt
, que ya estaba creado cuando creamos el certificado anteriormente)
$ cd ~/ghost
$ mkdir content
$ mkdir mysql
$ sudo mkdir -p /usr/share/nginx/html
Crea la imagen Docker de Nginx
El archivo Docker compose que hemos creado depende de la imagen Docker de Nginx. Para que funcione, tenemos que incluir un archivo de configuración personalizado para Nginx que funcione con Ghost.
Crea un directorio para esta imagen en el directorio actual.
$ mkdir nginx
Crea un archivo llamado Dockerfile
en este directorio.
$ touch nginx/Dockerfile
Pega el siguiente código en el Dockerfile
.
FROM nginx:latest
RUN rm /etc/nginx/conf.d/default.conf
COPY ghost.conf /etc/nginx/conf.d
El código anterior indica a Docker que utilice la última imagen de Nginx. También elimina el archivo de configuración de Nginx por defecto y copia el archivo de configuración personalizado que hemos creado para nuestro Ghost CMS.
Crea un archivo llamado ghost.conf
en el directorio nginx
.
$ touch nginx/ghost.conf
Pega el siguiente código en el archivo ghost.conf
. Sustituye todas las instancias de example.com
por tu dominio.
server {
listen 80;
listen [::]:80;
server_name example.com;
# Useful for Let's Encrypt
location /.well-known/acme-challenge/ { root /usr/share/nginx/html; allow all; }
location / { return 301 https://$server_name$request_uri; }
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
access_log /var/log/nginx/ghost.access.log;
error_log /var/log/nginx/ghost.error.log;
client_max_body_size 20m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://ghost:2368;
}
}
La configuración anterior redirigirá todas las peticiones HTTP a HTTPS y servirá como proxy para que el servicio de Ghost lo sirva a través de tu dominio.
Paso 5 - Ejecuta el sitio
Ejecuta el siguiente comando desde el directorio ghost
para iniciar el servicio Ghost.
$ docker-compose up -d
Ahora, puedes verificar tu instalación abriendo https://example.com
en tu navegador web. El Docker puede tardar varios minutos en activar todos los servicios, por lo que es posible que tengas que actualizarlo si no ves tu blog de inmediato.
Si tu sitio no aparece en el navegador, tienes que revisar los registros de Docker. Para ello, cierra primero tu contenedor.
$ cd ghost
$ docker-compose down
Ejecuta Docker compose en un estado adjunto para ver los registros generados por cada contenedor.
$ docker-compose up
Para cerrar el contenedor y volver al prompt de bash, pulsa CTRL+C
. Una vez que hayas terminado de solucionar el problema, puedes volver a ejecutar el contenedor y tu blog debería ser visible esta vez.
Paso 6 - Completar la configuración
Para terminar de configurar tu blog Ghost, visita https://example.com/ghost
en tu navegador. El extra /ghost
al final del dominio de tu blog te redirige al Panel de Administración de Ghost o, en este caso, a la configuración, ya que estás accediendo a ella por primera vez.
Aquí tendrás que crear tu cuenta de administrador y elegir un título para el blog.
También puedes invitar a otros miembros del personal o colaboradores para tu blog, lo que también puedes hacer más tarde si decides omitirlo ahora.
Al final de la configuración, aparecerá el panel de administración de Ghost.
Si quieres cambiar al modo oscuro, puedes hacerlo haciendo clic en el interruptor situado junto al botón del engranaje de configuración en la parte inferior de la página de configuración.
Ya verás algunas publicaciones por defecto que son básicamente guías para ayudarte a navegar y utilizar Ghost. Puedes despublicarlas o eliminarlas y empezar a publicar.
Paso 7 - Actualizar Ghost
En nuestro archivo de composición de Docker, estamos sacando la última versión de Ghost disponible en el momento de la instalación, lo que facilita la actualización de tu blog de Ghost.
Para actualizar, tienes que apagar tu contenedor, sacar las últimas imágenes y volver a ejecutar el contenedor.
$ docker-compose down
$ docker-compose pull && docker-compose up -d
Paso 8 - Renueva tu certificado SSL Let's Encrypt
Los certificados de Let's Encrypt sólo son válidos durante 90 días. Por lo tanto, necesitamos configurar un cronjob que renueve el certificado automáticamente.
Abre Crontab en tu editor.
$ sudo crontab -e
Pega la siguiente línea al final que ejecutará Certbot a las 11 de la noche todos los días. Sustituye example.com
por tu dominio.
0 23 * * * certbot certonly -n --webroot -w /usr/share/nginx/html -d example.com --deploy-hook='docker exec ghost_nginx_1 nginx -s reload'
Ejecutar a las 11 PM todos los días no significa que tu certificado se renovará todos los días, ya que Certbot renovará tu certificado sólo si su fecha de caducidad está dentro de los 30 días. Ejecutar esto cada noche da al script un número de oportunidades para intentarlo antes de la expiración.
El comando anterior también reiniciará el servidor Nginx dentro del contenedor Docker después de la renovación exitosa.
Puedes probar el cronjob utilizando la opción --dry-run
de Certbot.
$ sudo bash -c "certbot certonly -n --webroot --dry-run -w /usr/share/nginx/html -d example.com --deploy-hook='docker exec ghost_nginx_1 nginx -s reload'"
Conclusión
Con esto concluye nuestro tutorial sobre cómo configurar Ghost CMS en tu servidor basado en Ubuntu 20.04 utilizando Docker. Si tienes alguna pregunta o algún comentario, compártelo en los comentarios de abajo.