Here at Sandtable we love Docker because it makes our infrastructure so easy to deploy. However, it’s not great when you have 2GB Docker images that must be pushed and pulled over the network…
We noticed that Docker is now offering smaller images based on the security-oriented, lightweight Alpine Linux distribution. Images based on Alpine can be a lot smaller – for example, the python:2.7-alpine
image is 19MB while the python:2.7
image is 260MB! We therefore decided to follow the same path and refactor our Dockerfiles.
Here is our guideline on how to proceed.
FROM alpine
The first step is to change the base image in your Dockerfile:
FROM ubuntu => FROM alpine
FROM python:2.7 => FROM python:2.7-alpine
FROM ruby:2.3 => FROM ruby:2.3-alpine
Go to hub.docker.com to check whether an alpine image is available (for example: search for “python”, select the official image, and go to the “Tags” section).
APK instead of APT or YUM
For Alpine the main difference is the package management.
In your Dockerfile, replace:
RUN apt-get update && apt-get install <package>
with:
RUN apk add --no-cache <package>
apk –no-cache
The --no-cache
option allows you to not cache the index locally. First win!
ERROR: unsatisfiable constraints
The packages in Alpine are different and may have different names. You can search for available packages at this address: https://pkgs.alpinelinux.org/packages.
Package in the testing or community repository
The package you need may not be available in the main repository but in the the testing or community repositories. Here is how you can add it to your Dockerfile:
RUN echo "http://dl-4.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories RUN apk --update add --no-cache <package>
apk –virtual and del
There is a really cool feature that allows you to temporarily install packages (sort of). For example, you may need git or gcc to install your program but you don’t need them to execute it. In this case you will use the --virtual
flag and give a name to this group of packages. Then you will be able to remove all of them.
For example:
RUN apk add --no-cache --virtual .build-deps \ gcc \ freetype-dev \ musl-dev RUN pip install --no-cache-dir <packages_that_require_gcc...> \ RUN apk del .build-deps
Reduce the number of layers
You can also reduce your image size by reducing the number of layers. If you have several RUN commands in a row, convert them into one RUN. For the previous example:
RUN apk add --no-cache --virtual .build-deps \ gcc \ freetype-dev \ musl-dev RUN pip install --no-cache-dir <packages_that_require_gcc...> \ RUN apk del .build-deps
Then becomes:
RUN apk add --no-cache --virtual .build-deps \ gcc \ freetype-dev \ musl-dev \ && pip install --no-cache-dir <packages_that_require_gcc...> \ && apk del .build-deps
Note: this tip is valid for any image (not only those based on Alpine).
UPDATE 28/02/2017: Flatten the Docker image
Since the release of Docker 1.13, it’s possible to flatten your image. The --squash
option squashes the image layers to the FROM image after successful builds. Just add --squash
to your build command:
docker build --squash -t my_image .
This option is an experimental feature, so you need to start your Docker daemon with the --experimental
flag to be able to use it.
In Ubuntu for example, add the line: DOCKER_OPTS="--experimental=true"
to the /etc/default/docker
file and restart Docker to be able to use this feature.
How to add a user on Alpine?
This will create a system user:
RUN adduser -S <username>
Documentation:
adduser [OPTIONS] user_name Add a user Options: -h DIR Home directory -g GECOS GECOS field -s SHELL Login shell -G GRP Add user to existing group -S Create a system user -D Do not assign a password -H Do not create home directory -u UID User id
How to enter an Alpine container?
Alpine doesn’t come with bash, so to enter a container forget:
docker run -ti my_image bash
Simply use shell:
docker run -ti my_image sh
Conclusion
By moving to Alpine we have reduced Docker images to a third of their size – speeding up deployments. We hope you’ll have the same success. Don’t hesitate to leave us a comment below and share your tips!
Comments
Categories
Archive
- September 2019
- August 2019
- July 2019
- June 2019
- March 2019
- February 2019
- December 2018
- August 2018
- April 2018
- February 2018
- September 2017
- August 2017
- July 2017
- June 2017
- May 2017
- April 2017
- March 2017
- December 2016
- November 2016
- October 2016
- September 2016
- August 2016
- July 2016
- June 2016
- May 2016
- April 2016
- March 2016
- January 2016
- December 2015
- November 2015
- October 2015
- September 2015
- June 2015
- May 2015
- April 2015
- March 2015
- September 2014
- August 2014
- June 2014
- May 2014
- April 2014
- March 2014
- November 2013
- September 2013
- June 2013
- May 2013
- September 2012
- June 2012
- May 2012
- April 2012
- March 2012
Nice article. Very clear and simple steps that actually make a really big difference to the size of the image. Thanks
An “apk del” in an extra layer has no benefit. Removing files makes images larger, not smaller. You *must* “add” and “del” in the same layer to benefit from it.
Moreover, “apk del” also caches, so use the “–no-cache” option also there.