Sabbatical dev

sabbatical devtechnical blog
 

Containerise Strapi

Strapi on your cluster

I was amazed at how simple it was to get Strapi containerised and ready for my Kubernetes cluster. I use MongoDB Atlas for my database so I just needed to containerise the main project and overall this was an extremely painless process.

First off in the root of the project you have to add a Dockerfile and apply the following.

UPDATE:

Below is a naive approach that creates a docker image of around 1.83 GB

FROM strapi/base

WORKDIR /my-path

COPY ./package.json ./
COPY ./yarn.lock ./

RUN yarn install

COPY . .

ENV NODE_ENV production

RUN yarn build

EXPOSE 1337

CMD ["yarn", "start"]


The best I found was this solution

FROM node:14-alpine as BUILD_IMAGE

WORKDIR /strapi

# Resolve node_modules for caching
COPY ./package.json ./
COPY ./yarn.lock ./
RUN yarn install --production=true --frozen-lockfile

# Copy all for build and release cache if package.json update
COPY . .
ENV NODE_ENV=production

RUN yarn build

#------------------------------------------------------------------------------------

# Create new namespace for final Docker Image
FROM node:14-alpine

# Only copy your source code without system file
COPY --from=BUILD_IMAGE /strapi /strapi

WORKDIR /strapi

EXPOSE 1337

ENV NODE_ENV=production
ENV STRAPI_LOG_LEVEL=debug

CMD ["yarn", "start"]


This reduces the image to around 500MB

you will also need need to add a .dockerignore file and apply

UPDATE I added more to my docker ignore, below node_modules, this also added some further reduction

.dockerignore
.gitignore
README.md
build


With this in place you are ready to build and tag your image. I use github as my image repository so this was my command.

docker build -t docker.pkg.github.com/esharmony/personal-blog-strapi/personal-blog-strapi:0.0.6 .


All done and ready to pushed to the repo and pulled from my cluster - nice!

A couple of other things you may come across.

CORS

I added some CORS settings for security. For this you need to add a new file in your config folder config/middleware.js and apply

module.exports = {
  //...
  settings: {
    cors: {
      origin: [
        "http://localhost", // just in case :)
        "http://localhost:3000", // my localhost with port
        "https://www.sabbaticaldev.co.uk", // my frontend url
        "https://sabbaticaldev.co.uk", // my frontend url
        "https://yourclusterurl.domext", // for strapi admin portal on your cluster
      ],
    },
  },
};

Environment Variables

I had two main changes I needed to make for my live environment.

The first is the database

The second is I had to supply a path to the base url that strapi was being served from by my cluster.

In strapi your environments are handled via overriding your config files by adding a couple of directories inside your config directory. Add an env directory inside config then inside that a production directory so you now have

config/env/production


For the production database I created some new PROD environment variables in my .env file ( I did not create another .prod.env. or anything)

Then I created a database.js file inside the new production directory

config/env/production/database.js 


and applied

module.exports = ({ env }) => ({
    defaultConnection: 'default',
    connections: {
      default: {
        connector: 'mongoose',
        settings: {
          host: env('DATABASE_HOST_PROD'),
          database: env('DATABASE_NAME_PROD'),
          username: env('DATABASE_USERNAME_PROD'),
          password: env('DATABASE_PASSWORD_PROD'),
        },
      },
    },
  });


Strapi merges the database.js from the config folder root and the new production database.js file together and overrides the root config file with the environment one.

The strapi base url

Because I was not serving strapi from the root of my cluster so http://myclusterurl.co.uk/ I found I got an error when trying to access the admin portal.

To fix this I needed to add a path to let strapi know the root. This has to be applied to the server.js file in config but again only for production. So again I created a server.js file in the new production directory

config/env/production/server.js 


and applied

module.exports = ({ env }) => ({
  url: env("URL"),
});


The URL in the .env file points to my root path for strapi designated by my ingress controller as an absolute url.

If this was any used to you please let me know, or if you need any further info comment or find me on twitter @DevSabbatical


Comments

Add a comment