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