How did I reduce the docker image of SimplCommerce from 900M to 145M using multi-stage builds
Always looking for better ways to do thing is one of our principles for building SimplCommerce. Last week, I made another refactoring for our automated docker build by applying multi-stage builds. We were able to reduce the SimplCommerce image size from 900M to 145M (compressed). In this blog post, I will describe how we did that.
First, let review the situation: We want to run a docker automated build for every change happens on master branch.
One of our problems is that the docker image size is quite big around 900M (compressed). Because it have to include everything so that it can build the application by itself such as dotnet core sdk, nodejs, gulp, and all the source code.
Recently, Docker has introduced multi-stage build.
With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image
By applying multi-stages build I have divided the SimplCommerce Dockerfile into 2 stages:
The first stage
In the first stage, I use the simplcommerce/simpl-sdk as a base image. Basically, it is an image contains dotnet core sdk, nodejs and gulp-cli
Because the SimplCommerce source code is using MSSQL, I run some SED commands (find and replace) to make it work for PostgeSQL.
Install gulp and run “copy-modules” gulp task to copy all the modules to the host. SimplCommere is built based on modular architecture
I also need to delete all added migrations and run add migration again the because the difference between MSSQL and PostgreSQL.
dotnet ef migrations script -o dbscript.sql will generage sql script for the database schema.
Publish the website.
However, The generated sql file is utf-8 encoded which having issue when run by psql command.
The psql command gives syntax errors when fed .sql files that are saved with encoding “UTF-8” and contain a BOM (byte order marker)
- Remove the BOM in sql script by SED commands
The second stage
The runtime only microsoft/aspnetcore:2.0.0-preview2-jessie image is used as the base. We also need to install postgresql-client in order to execute .sql scripts.
I have named the first stage “build-env” by adding an
AS build-env to the FROM instruction. So, we can use that name in the COPY instructions
RUN chmod 755 /docker-entrypoint.sh to set execute permission for the docker-entrypoint.sh
When the docker run it will execute the docker-entrypoint.sh which will connect to PostgreSQL create database, tables and insert some pre-defined data if needed.
At this time Docker Hub has NOT supported multi-stage builds. Fortunately, Docker Cloud has supported it and it’s free also