When you create the container image for your application, you need to set a base container image (indicated in the FROM statement from Dockerfiles/Containerfiles). Usually, we set Linux distributions as base images like Debian, CentOS, or Ubuntu. Later, we install all the libraries we need to build and/or run our application and generate the final container image. If we’re working with Java, we’ll install Gradle or use an image with Gradle installed. If we’re using Python, we’ll install the Python runtime or use an image with Python installed by default.
One of the recommendations given as a good practice is to create minimal container images. What is a minimal container image? A container image with only your application, the configurations (XML files, environment variables), and the dependencies. Following this approach, we reduce the size of our container images. Why is this interesting? The images will be cheaper to store and to pull/push from/to container registries.
Depending on the technologies your application relies on, you will depend more or less on the base image. For example, if you develop in NodeJS or Python, you only need a base image with the runtime installed: you don’t care about the base OS. If you develop in C, you probably need to care about it because you may need to depend on a specific LIBC implementation (GLIBC or MUSL, for instance). So, to productize your application, you should choose a base container image that meets your requirements but minimal footprint. For instance, if we need to use a NodeJS Carbon container image as a base for ours, carbon-alpine is the best choice.
|Repository||Tag||Image ID||Size (MB)|
But, if we’re using something as Golang, were you can do static link of everything into your application, you can reduce the size even more. Why? Because you don’t need a runtime and you can, even, not need a base operating system. For that reason, is pretty common to see Dockerfiles from Golang applications as simple as (supposing the application was built locally or you can use multi-stage container builds)
FROM scratch COPY myapp . ENTRYPOINT [“./myapp”]
Is using scratch images a good idea?
Using scratch images as the base for containers can be a good idea because they provide a minimal and clean starting point for building images. The scratch image is completely empty and does not include any pre-installed packages or libraries, which means that you have complete control over the dependencies and software that are included in the image. It is the 0 image. The “Object” container image. The minimal container image. The nothing.
Using scratch images as the base for our containers can be beneficial in situations where you need to build a small, lightweight image that only includes the exact packages and libraries that are necessary for your application. Following this approach can help you to ensure that your images are more secure since there are no pre-installed packages or libraries that could be vulnerable to security exploits.
Some developers prefer not to use scratch images as a base for their container images. They can be “safer” because they don’t have applications the hackers can take advantage of to break into your system but they do not provide any security or patching mechanisms. This is usually a concern for developers. Instead, many developers prefer to use base images that include a minimal set of commonly-used packages and libraries, which can save time and reduce the risk of errors, even when the base images are not totally minimal. A good approach for this can be to use the distroless container base images, where you have base images but not with a lot of components.
And you? What do you prefer to use?
Top comments (0)