Hace unos días un cliente puso sobre la mesa un proyecto en el que su equipo quería usar Strapi como CMS. Siendo sincero no he leído o escuchado mucho sobre Strapi, así que siempre, lo primero que se me ocurre es “¿cómo puedo usar docker para no llenar de cosas mi compu?”. Así que el objetivo del post es ver cómo dockerizar Strapi con Postgres (PostgreSQL).
¿Qué es Strapi?
El objetivo del post no es indagar en Strapi, pero en el futuro, cuando lo conozca más, trataré de hacer algunos posts sobre esta tecnología.
Por ahora solo diremos que es un CMS headless de código abierto y cuyo objetivo es la gestión del contenido como blogs, una tienda en línea o una app, y nos podemos conectar a ella mediante su API.
Iniciar un proyecto
Antes de iniciar debemos tener instalado lo siguiente:
Primero vamos a crearnos un proyecto de Strapi:
npx [email protected] strapi-pg-docker --quickstart
Si tumbamos el proceso (ctrl + c), podemos reiniciarlo con npm run develop
.
Una vez finalizado el proceso, se abrirá tu navegador y mostrará esta pantalla para que creemos nuestro usuario administrador y comenzar a usarlo.
Como ya dije, no entraremos en detalle con Strapi, pero ya estamos listos para crear nuestro primer COLLECTION TYPE.
Configurar Strapi
Por ahora no hemos configurado nada, ni MySQL ni Postgres para que Strapi se conecte a una base específica. ¿Strapi instala algo? No, si vemos en la ruta config\database.js
, vemos que por default, nos aparece SQLite como el motor predeterminado.
module.exports = ({ env }) => {
const client = env('DATABASE_CLIENT', 'sqlite');
Y si vemos el archivo .env
está configurado lo siguiente:
DATABASE_CLIENT=sqlite
DATABASE_FILENAME=.tmp/data.db
Nos indica que el cliente es sqlite
y el archivo de la base de datos está en .tmp\data.db
. Para que funcione nuestro proyecto, el archivo data.db
será gestionado por el paquete better-sqlite3
que está en las dependencias de nuestro package.json
.
Postgres en Docker
Como nuestro objetivo es dockerizar nuestro Strapi con PostgreSQL, tenemos que crear y configurar lo necesario. Primero vamos a crear el archivo docker-compose.yml
con el siguiente contenido:
version: "3"
services:
strapiDB:
container_name: strapiDB
platform: linux/amd64 #for platform error on Apple M1 chips
restart: unless-stopped
env_file: .env
image: postgres:14.5-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- ./volumes/postgres:/var/lib/postgresql/data
ports:
- "5432:5432"
Esta configuración usa la versión 14.5 de PostgresQL y vamos a montar un volumen dentro de nuestro propio directorio, al que llamaremos volumes
.
También vamos a agregar al archivo .env
tres variables:
POSTGRES_DB=strapidb
POSTGRES_USER=strapi
POSTGRES_PASSWORD=strapi
Y cambiar DATABASE_CLIENT
de “sqlite
” a “postgres
“.
También vamos a editar el archivo config\database.js
. Al igual que en el .env
cambiaremos de “slite
” a “postgres
“.
module.exports = ({ env }) => {
const client = env('DATABASE_CLIENT', 'postgres');
Ahora agregamos el paquete de Node para que nos controle la conexión con PostgreSQL.
npm install pg
Una vez instalado la librería pg
podemos probar nuestro contenedor:
docker-compose up -d strapiDB
Strapi en Docker
Para terminar de dockerizar strapi con postgresql, vamos a crear y editar algunos archivos.
Crear archivo Dockerfile
FROM node:18-alpine
# Installing libvips-dev for sharp Compatibility
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev git
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY package.json package-lock.json ./
RUN npm install -g node-gyp
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install
ENV PATH /opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN chown -R node:node /opt/app
USER node
RUN ["npm", "run", "build"]
EXPOSE 1337
CMD ["npm", "run", "develop"]
Creamos .dockerignore
:
.tmp/
.cache/
.git/
.env
build/
node_modules/
# Ignoring folders that might be used in starter templates
data/
backup/
Ahora modificarmos el docker-compose.yml
:
version: "3"
services:
strapi:
container_name: strapi
build:
dockerfile: Dockerfile
restart: unless-stopped
env_file: .env
environment:
DATABASE_CLIENT: postgres
DATABASE_HOST: strapiDB
DATABASE_NAME: ${POSTGRES_DB}
DATABASE_USERNAME: ${POSTGRES_USER}
DATABASE_PORT: 5432
JWT_SECRET: ${JWT_SECRET}
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
NODE_ENV: development
volumes:
- ./volumes/public/uploads:/opt/app/public/uploads
- ./config:/opt/app/config
- ./src:/opt/app/src
- ./package.json:/opt/package.json
- ./yarn.lock:/opt/yarn.lock
ports:
- "1337:1337"
depends_on:
- strapiDB
strapiDB:
container_name: strapiDB
platform: linux/amd64 #for platform error on Apple M1 chips
restart: unless-stopped
env_file: .env
image: postgres:14.5-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- ./volumes/postgres:/var/lib/postgresql/data
ports:
- "5432:5432"
NOTA: cambiamos los permisos de volumes
, ya que deben ser usados por otro contenedor y nos dará error si intentamos levantar el contenedor strapi
.
sudo chown -R $USER:$USER volumes
Si no tienes a Docker ejecutándose con tus permisos de usuario, puedes darle todos los permisos:
sudo chmod 777 -R _docker_volumes
Listo, ejecutamos lo siguiente y a disfrutar 😀
docker-compose up strapi
Este proceso puede tardar más o menos, de acuerdo a tu red y capacidad de la máquina.
NOTA: es común ejecutar docker-compose
con el switch -d
para que el proceso corra en background sin que nos bloquee, pero no lo recomiendo al principio, porque en caso de error no podremos ver qué está pasando (aunque podemos ejecutar docker logs strapi
) y consume en muchos casos la CPU.
Abrimos el navegador y ejecutamos http://localhost:1337/
. Con esto hemos terminado de dockerizar strapi con postgres.
Gracias por leer.