What is Strapi?
Strapi is an open-source headless CMS (Content Management System) that enables developers to create and manage content-rich applications effortlessly. It provides a powerful and flexible back-end infrastructure while allowing you to use any front-end technology you prefer, such as React, Vue.js, or Angular.
Benefits of Using Strapi
- Flexibility: build APIs tailored to your needs and integrate them with any front-end framework or platform.
- Efficiency: Save development time with automatic API generation and a user-friendly content management interface.
- Community and Support: As an open-source project, Strapi has a growing community of developers contributing to its ecosystem, offering plugins, tutorials, and support.
Strapi is an excellent choice for developers seeking a customizable, efficient, and powerful CMS to manage and deliver content seamlessly across multiple platforms.
Automate Strapi deployment
Before you start automating the deployment of Strapi to an instance, you need a few things:
- dockerize Strapi
- Google instance
- Google storage bucket for database backup and
- GitLab cI script.
Running Strapi in a Docker Container
Using Docker Compose simplifies managing complex application environments by offering:
- Consistency: ensures consistent setups across environments.
- Simplified Configuration: manages all configurations in one YAML file.
- Scalability: easily scale applications up or down.
- Dependency Management: handles multiple dependencies effortlessly.
- Backup and Restore: encapsulates the entire stack for easy backup.
For easy backup:
- Backup Docker Compose file: contains application definitions.
- Backup Data Volumes: export persistent data volumes.
- Version Control: store files in Git for tracking changes.
- Automate Backup Tasks: set up automated backups for efficiency.
Using Docker to run Strapi can streamline the setup process and ensure a consistent environment across different development stages. Here's a step-by-step guide to get Strapi up and running in a Docker container:
FROM node:18-alpine3.18
# 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 yarn.lock ./
RUN yarn global add node-gyp
RUN yarn config set network-timeout 600000 -g && yarn install
ENV PATH /opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN chown -R node:node /opt/app
USER node
RUN ["yarn", "build"]
EXPOSE 1337
CMD ["yarn", "develop"]
Now it's time to write Docker Compose:
version: "3"
services:
strapi:
container_name: strapi
build: .
image: strapi:latest
restart: unless-stopped
env_file: .env
environment:
DATABASE_CLIENT: ${DATABASE_CLIENT}
DATABASE_HOST: strapiDB
DATABASE_PORT: ${DATABASE_PORT}
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_USERNAME: ${DATABASE_USERNAME}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
APP_KEYS: ${APP_KEYS}
NODE_ENV: ${NODE_ENV}
volumes:
- ./config:/opt/app/config
- ./src:/opt/app/src
- ./package.json:/opt/package.json
- ./yarn.lock:/opt/yarn.lock
- ./.env:/opt/app/.env
- ./public/uploads:/opt/app/public/uploads
ports:
- "1337:1337"
networks:
- strapi
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:12.0-alpine
environment:
POSTGRES_USER: ${DATABASE_USERNAME}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
POSTGRES_DB: ${DATABASE_NAME}
volumes:
- strapi-data:/var/lib/postgresql/data/ #using a volume
#- ./data:/var/lib/postgresql/data/ # if you want to use a bind folder
ports:
- "5432:5432"
networks:
- strapi
volumes:
strapi-data:
networks:
strapi:
name: Strapi
driver: bridge
Database Backup
Now it is very important to write a shell script and set up a cron job to run every day for a base backup on Google Cloud Bucket.
echo "0 4 * * * /usr/share/strapi/base_backup.sh" | crontab -
Here is an example of the script:
#!/bin/bash
# Source the .env file
source /usr/share/strapi/.env
# Step 2: Connect to the PostgreSQL container and perform backup
docker compose exec -T strapiDB sh << 'EOF'
# Step 3: Execute the backup command (inside the container)
pg_dump -U postgres -d postgres > /var/lib/postgresql/data/backup_$(date +%Y%m%d).sql
EOF
# Step 5: Copy the backup file from the container to host
docker cp $(docker compose ps -q strapiDB):/var/lib/postgresql/data/backup_$(date +%Y%m%d).sql /usr/share/strapi/backup_base/
# Step 6: Upload the backup file to Google Cloud Storage
gsutil cp /usr/share/strapi/backup_base/*.sql gs://$STORAGE_CLOUD_DB/
Now you have a ready Docker Compose file and a database backup shell script. You can now write a GitLab CI script to automatically connect to the instance and run Docker Compose for Strapi.
You can connect to the instance using SSH with GitLab CI, copy the Docker Compose file, and then run it.
In GitLab CI, you can define two types of deployment stages: "stage" and "prod". These stages help organize the deployment process, allowing for distinct actions at different points in the pipeline. For example, you can designate the "stage" stage to run when you merge changes into the main branch, ensuring that your developments are thoroughly tested before moving further. Conversely, you assign the "prod" stage to execute when you tag a release, indicating that the code is ready for production deployment. This separation of stages streamlines the deployment workflow, enhancing efficiency and reliability in software delivery.
Cost-saving advice
In addition to optimizing your deployment pipeline, there are further strategies you can employ to reduce expenses in cloud infrastructure. For instance, if you maintain a staging instance for testing and development purposes, it may not be necessary to keep it running continuously. Leveraging features provided by platforms like Google Cloud, you can schedule the instance to automatically turn on and off based on your usage patterns.
By implementing this proactive approach, you can significantly lower your operational costs while still maintaining the flexibility and accessibility of your staging environment.
This simple yet effective cost-saving measure demonstrates your commitment to efficient resource management and financial sustainability in your cloud operations.