Docker Images : Part II - Details Specific To Different Languages

Docker Images : Part II - Details Specific To Different Languages

Series Index Reducing Image Size Details Specific To Different Languages Going Farther To Reduce Image Size Introduction In the first part, we introduced multi-stage builds, static and dynamic linking, and briefly mentioned Alpine. In this second part, we are going to dive into some details specific to Go. Then we will talk more about Alpine, because it’s worth it; and finally we will see how things play out with other languages like Java, Node, Python, Ruby, and Rust.

Introduction

In the first part, we introduced multi-stage builds, static and dynamic linking, and briefly mentioned Alpine. In this second part, we are going to dive into some details specific to Go. Then we will talk more about Alpine, because it’s worth it; and finally we will see how things play out with other languages like Java, Node, Python, Ruby, and Rust.

So, what about Go?

You might have heard that Go does something very smart: when building a binary, it includes all the necessary dependencies in that binary, to facilitate its deployment.

You might think, “wait, that’s a static binary!” and you’d be right. Almost. (If you’re wondering what a static binary is, you can check the first part of this series.)

Some Go packages rely on system libraries. For instance, DNS resolution, because it can be configured in various ways (think /etc/hosts/etc/resolv.conf, and some other files). As soon as our code imports one of these packages, Go needs to generate a binary that will call system libraries. For that, it enables a mechanism called cgo (which generally speaking, allows Go to call C code) and it produces a dynamic executable, referencing the system libraries that it needs to call.

This means that a Go program that uses e.g. the net package will generate a dynamic binary, with the same constraints as a C program. That Go program will require us to copy the needed libraries, or to use an image like busybox:glibc.

We can, however, entirely disable cgo. In that case, instead of using system libraries, Go will use its own built-in reimplementations of these libraries. For instance, instead of using the system’s DNS resolver, it will use its own resolver. The resulting binary will be static. To disable cgo, all we have to do is set the environment variable CGO_ENABLED=0.

For instance:

FROM golang
COPY whatsmyip.go .
ENV CGO_ENABLED=0
RUN go build whatsmyip.go

FROM scratch
COPY --from=0 /go/whatsmyip .
CMD ["./whatsmyip"]

Since cgo is disabled, Go doesn’t link with any system library. Since it doesn’t link with any system library, it can generate a static binary. Since it generates a static binary, that binary can work in the scratch image. 🎉

Tags and netgo

It’s also possible to select which implementation to use on a per-package basis. This is done by using Go “tags”. Tags are instructions for the Go build process to indicate which files should be built or ignored. By enabling the tag “netgo”, we tell Go to use the native net package instead of the one relying on system libraries:

go build -tags netgo whatsmyip.go

If there are no other packages using system libraries, the result will be a static binary. However, if we use another package that causes cgo to be enabled, we’re back to square one.

docker images java node python netgo

What is Geek Coin

What is GeekCash, Geek Token

Best Visual Studio Code Themes of 2021

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

top 30 Python Tips and Tricks for Beginners

In this post, we'll learn top 30 Python Tips and Tricks for Beginners

Lambda, Map, Filter functions in python

You can learn how to use Lambda,Map,Filter function in python with Advance code examples. Please read this article

How to Install OpenJDK 11 on CentOS 8

What is OpenJDK? OpenJDk or Open Java Development Kit is a free, open-source framework of the Java Platform, Standard Edition (or Java SE).

Going Beyond Java 8: Local Variable Type Inference (var) - DZone Java

In this article, we will talk about the most important new feature introduced with Java 10, officially called local variable type inference. An extremely important function in java. You will regret skipping this article.

Sharing Docker Images on Docker Hub

An image like the one we created in the Node.js Hello World Docker Container from scratch post is simple, yet it’s a perfect example to try one of the cool features of Docker, provided through Docker Hub, the official hosting service of public and private Docker Images. Before we can do that, however, we need to register on Docker Hub. Docker Hub is free in its basic plan which includes unlimited public repos and one private repo.