Hey guys! I am fairly new to Docker and just managed to build my first few images with this Dockerfile:
FROM strapi/base
WORKDIR /src/app
COPY ./package.json ./
COPY ./yarn.lock ./
RUN yarn install
COPY . .
ENV NODE_ENV production
RUN yarn build
EXPOSE 1337
CMD ["yarn", "start"]
It works, however the image size is about 1.83GB big. I have read a bit about multistage docker builds and how they can drastically reduce the size. Unfortunately I am not sure how to set it up though.
I also tried to build the image with FROM: node:alpine but the file size was still 1GB and Strapi failed to run with yarn start due to a problem with the node sharp module.
Any advice for me to decrease the image size? Highly appreciate your help for a Docker newbie.
I had the node_modules folder in my .gitignore already.
Regarding the other two parts. Thanks for clarifying the sharp problem. The missing build-essential is probably what caused the problem.
Would it be possible for you to post an example Dockerfile of what you exactly mean? I looked at the base/alpine files but can’t wrap my head around yet how to setup the full Dockerfile now…
Don’t forget to add the .git directory to dockerignore. Since it is also copied into the image, with all the commits history, branches and etc. If you have a big repo with 10-20 branches of your project that can increase the image’s size a lot.
I don’t have a complete Dockerfile for alpine, since I’m using Debian, but they must be pretty similar. You can take a look at one of my docker files for google cloud by using debian, I’ve also left a few comments inside it:
#use debian image
FROM debian:10
#install all the dependencies that are need on debian to run strapi project with nginx and pm2.
RUN apt-get -y update
RUN apt-get install -y git ca-certificates nginx-full bash nano ssl-cert curl gzip zip python make gcc g++ wget gnupg2 dialog apt-utils
RUN curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install -y yarn
RUN apt-get install -y build-essential
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - \
&& apt-get install -y nodejs
#copy only the files that I need to run the project
RUN mkdir www/
COPY api/ /www/api
COPY admin/ /www/admin
COPY config/ /www/config/
COPY extensions/ /www/extensions
COPY public/ /www/public
COPY docker/ /www/docker/
COPY plugins/ /www/plugins/
COPY components/ /www/components/
COPY package.json /www/
COPY ecosystem.config.js /www/
COPY /docker/nginx/nginx.conf /etc/nginx/
WORKDIR /www
#making the sh files executable, you can avoid this part.
RUN chmod +x ./docker/entrypoint.sh
RUN chmod +x ./docker/cloud_sql_proxy
RUN echo "unsafe-perm = true" >> ~/.npmrc
#install only the production packages, also reduces the size/time of install
RUN yarn install --only=production && yarn global add pm2
#building the admin panel for production
RUN NODE_ENV=production yarn build
VOLUME /etc/www
EXPOSE 1337
EXPOSE 80
STOPSIGNAL SIGTERM
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
RUN make-ssl-cert generate-default-snakeoil --force-overwrite
#In entrypoint we start nginx/gcloud SQL proxy. And as the last step it runs the pm2 process with ecosystem config file configured for strapi.
#that part can also be avoided, you can use yarn start if you don't want to use pm2.
ENTRYPOINT /www/docker/entrypoint.sh
Hi, I want share my Dockerfile, run on stock Strapi v3.6.3.
Use docker Buildkit.
Build time about 2’30s on Macbook Pro 2015.
Image size about ~500MB.
Hope this can help you. ^^
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"]
Hi all,
I typically deploy Strapi backend separately from the front-end. The front-end is Webpack’d and deployed on static hosting with CDN.
Now, when deploying a Docker image of the backend, even at 500MB, it is huge! All of the front-end dependencies (Webpack, React, etc) are essentially installed along with it. Either if they are packaged in the image, or installed when the image is built, the entire huge dependency tree of the front-end and back-end are pulled in at some point.
Because of how Strapi is structured, I haven’t figured out a way to omit all the front-end dependencies when deploying the back-end separately…
To me it is confusing that in production (after running the build command) you still need the src folder present. Why is this? is it possible to somehow only serve the static files in the build folder? If not what is the purpose of this build folder?
Hi all,
I’ve published a utility called lockfile-shaker and a corresponding configuration for Strapi lockfile-shaker-strapi.
Basically what it does is edit your package-lock.json to safely make all of the dependencies that are only needed for the Strapi Admin front-end into dev-only dependencies. Then when you run npm ci --only production in your Docker build, it will only install the dependencies that are required for the backend server to run (not React, Webpack and all of those only require for the front-end) .
I use this in production and it reduces the number of dependencies in my server Docker image by 1350 packages, saving image build time, and reducing the image size by several hundred MB.
When you create content types you will see new folders/files for each type added under src/api directory. It also contains two other folders: admin and extensions. None of this is actual source code, it’s part of how strapi operates. So the name src might just be misleading?
A bit late to the party but I made a tool for this
This now has a production option and the Dockerfile.prod will be around 500-600MB depending if you are using npm or yarn (yes it’s a difference yarn is smaller)