Зарегистрируйтесь сейчас для лучшей персонализированной цитаты!

Understanding Container Images, Part 2: Optimizing Your Images

Feb, 01, 2021 Hi-network.com

In|the|first post of this series we discussed how container images are built. We talked about layers, reusing them, and how to make your Dockerfiles build faster.

We also started to build a container containing our shiny 'Hello World' C application.

Hello world app -Take 2

What is the ultimate goal of our container? In this case, we want to be able to build our application in an automated and consistent way, and then use it in our environment.

The first Dockerfile we wrote to build our Hello world app is:

FROM ubuntu:18.04RUN apt-get updateRUN apt-get install -y build-essentialWORKDIR /appCOPY app/hello.c /app/RUN gcc -o hello hello.cENTRYPOINT [ "/app/hello" ]

After building it, you can notice the size of the final container:

$docker build -t stage0 .
$docker image lsREPOSITORY   TAG       IMAGE ID       CREATED         SIZEstage0       latest    87a0e7eb81da   4 minutes ago   319MBubuntu       18.04     2c047404e52d   7 weeks ago     63.3MB$

319 Mb (a delta of 255 Mb over the ubuntu image) for a minimal hello world C app. Not exactly optimal. Additionally, if we jump into the container, we can see all our source code, compilation artifacts, etc. Not something you want to include in your shipping product.

The builder pattern

One of the problems with this approach is we're doing two very different things with our container: we're using it to build a product, and we're using the same one to ship it. Not optimal.

One common approach to solve this problem is to use two dockerfiles; one for building and one for shipping the product. During build, you can extract the built application to a local directory, and copy the files to the shipping container. This is called "the builder pattern".

Please read on, butdon't apply this ... yet. There are better ways!

The first dockerfile is almost identical to our first approach, except for the last line where ENTRYPOINT is defined:

Dockerfile.build:
FROM ubuntu:18.04RUN apt-get updateRUN apt-get install -y build-essentialWORKDIR /appCOPY app/hello.c /app/RUN gcc -o hello hello.c

You can now build this container and, after it's completed, extract the application from it. To build it, you need to specify the filename you want to use as your Dockerfile -Dockerfile.build on this example. Also, we're adding a name to the built image (build_step).

$docker build . -f Dockerfile.build -t build_step
$docker image lsREPOSITORY   TAG       IMAGE ID       CREATED            SIZEbuild_step   latest    f0e92c66ae80   About a minute ago 308MBubuntu       18.04     c090eaba6b94   10 hours ago       63.3MB$

Now you need to create a container from this image, extract the compiled application, and copy it to your filesystem:

$docker create --name extract build_step
$docker ps -aCONTAINER ID    IMAGE      COMMAND        CREATED          STATUS    PORTS    NAMESf22b7931ece6    build_step "/bin/bash"    6 seconds ago    Created            extract$mkdir built-app
$docker cp extract:/app/hello built-app/

And finally you have your compiled application:

$ls -l built-apptotal 24-rwxr-xr-x 1 fsedanoc staff 8304 Jan 21 15:03 hello$

 

Now you can build a simple Dockerfile to create the minimal environment to run your app:

Dockerfile
FROM ubuntu:18.04WORKDIR /appCOPY built-app/hello /app/ENTRYPOINT ["/app/hello"]
$docker run ship_stepHello from the container!$

If you look at the size of the images, the shippable one is much smaller -Actually it's just the base image plus our final application:

$docker image lsREPOSITORY   TAG       IMAGE ID       CREATED         SIZEship_step    latest    25cebe417392   5 minutes ago   63.3MBbuild_step   latest    f0e92c66ae80   19 minutes ago  308MBubuntu       18.04     c090eaba6b94   11 hours ago    63.3MB$

 

Simplyfing the build process

While the 'Builder pattern' works, keeping two separate Dockerfiles, plus scripts to extract the application from one to the host directory, etc, can become difficult to manage. There's a better way!

Multi-stage dockerfiles!

If you read the documentation for the Dockerfile, you can see the COPY file accepts an extra parameter:

--from

Per the documentation:

OptionallyCOPYaccepts a flag--from=<name>that can be used to set the source location to a previous build stage (created withFROM .. AS <name>) that will be used instead of a build context sent by the user

This flag allows you to compress the two steps in the Builder pattern in a single Dockerfile:

FROM ubuntu:18.04 as build_stepRUN apt-get updateRUN apt-get install -y build-essentialWORKDIR /appCOPY app/hello.c /app/RUN gcc -o hello hello.cFROM ubuntu:18.04WORKDIR /appCOPY --from=build_step /app/hello /appENTRYPOINT [ "/app/hello" ]
$docker build -t multistep .
After the build, you can see the final image, with the correct size, and as lean as it can be. You're ready to push your final image to the repository and use it to run your app!
$docker image lsREPOSITORY   TAG       IMAGE ID       CREATED         SIZEmultistep    latest    31ddecae27b8   9 minutes ago   63.3MB<none>       <none>    c301e0bb00e0   9 minutes ago   308MBubuntu       18.04     c090eaba6b94   11 hours ago    63.3MB
$docker run multistepHello from the container!$

Multi step builds are a great tool that will improve the quality of your containers. A smaller container means faster pushes and pulls, and that's crucial in a CI/CD/CD environment

For any question or comment, please let me know on the section below or also in Twitter or Linkedin

Related resources

  • Cisco lab -Docker 101
  • Cisco lab -Docker 201
  • Cloud & Container DevNet Learning Labs - Learn how containers and microservices can simplify your Cisco cloud deployments.


We'd love to hear what you think. Ask a question or leave a comment below.
And stay connected with Cisco DevNet on social!

Twitter @CiscoDevNet | Facebook | LinkedIn

Visit the new Developer Video Channel


tag-icon Горячие метки: Cisco DevNet docker Docker Containers

Copyright © 2014-2024 Hi-Network.com | HAILIAN TECHNOLOGY CO., LIMITED | All Rights Reserved.