A big image is not (always) good if it contains build and development tools.
I spent the two last days working on the Docker used for this blog following this base concept:
The image used during the development is maybe not the best one for the production environment.
In the end a sure thing was that I didn't needed a 1GB image just to run the Ghost Blog. Into the image there were lot of useless stuffs and lot of intermediate layers.
Step 1: Change the Docker base image
Before I was using the Node 6 which is the best one when you are developing a NodeJS application but it is containing lot of stuffs which are not necessary in production. Now I decided to use the alpine version of Node. What is the difference? 265Mb vs 19Mb !!
Step 2: Docker Multi-stage build
Since the 17.05 version, Docker introduces the multi-stage builds: in the same Dockerfile you can now use multiple FROM statements. Each of them can use a specific image and is basically starting a new stage of build. You can then copy artifacts from 1 stage to another.
Ex: Stage 1: build front application from sources Stage 2: build java back application from source Stage 3: create the final image getting binaries from Stage 1 and Stage 2
In this way you can add to the Stage 1 the packages required to build and check the front application, in the Stage 2 the java utils/library/packages to build the application... but in the final image (the one you want to deploy in production) you don't need all this build tools.
You can check the result of this big refactor looking to this Dockerfile. The installation of Ghost, using the GhostCLI, is not correctly working in the node alpine image. For this build stage I used the standard node image, but it is not the one used in the final container.
Step 3: Removed the Ghost database migration script
I also decided to separate the Ghost database migration script and the Ghost Blog. So far I used the migration script only 2 times, but it is taking lot of space in the blog image.
Right now there is a new Docker we can use when a database migration is required.
docker run -it --rm --name blogmigrate -e NODE_ENV=production -e DB_CURRENT_VERSION=1.0.2 -v /Users/mmornati/ghost-blog-test:/ghost-override mmornati/docker-ghostdbmigrate:v1.8.6
You have naturally to use the same version of the Ghost blog you want to run !
Impressive, isn't it? :)