liveBook · Manning

Container image

As explained in Shipping Go: Develop, deliver, discuss, design, and go again

A container image is a packaged, immutable filesystem and metadata bundle from which a container can be created.

Your team has a Go service that another team needs to run. Sharing a binary may still leave them sorting out how to start it and which dependencies it needs. A container image packages what the service needs for a container runtime; think of it as a template from which you can start many containers. The receiving team can pull and run the image without building the service or knowing Go. section 7.1 section 7.4

Images can build on other images. A base image might provide an operating system or language environment, with an application added above it. A registry stores images so a team can pull one to run or use it as a base. Publish the image as a pipeline artifact rather than asking every consumer to build it locally. section 7.4

Choose how much of the image build to control:

  • Use a Buildpack when you want to provide source code and let the build process detect the language and assemble the image. For a Go project, detection can look for Go files or a .mod file. section 7.2
  • Write a Dockerfile when you need a smaller production image or a separate development image for debugging. That gives you control over the base image and what each stage contains. section 7.6
Listing 7.3 Dockerfile
FROM golang:1.18 AS deps               #1
 
WORKDIR /hello-api                     #2
ADD *.mod *.sum ./
RUN go mod download                    #3
 
FROM deps as dev                       #4
ADD . .                                #5
EXPOSE 8080
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-w -X main.docker=true" \
    -o api cmd/main.go                 #6
CMD ["/hello-api/api"]
 
FROM scratch as prod                   #7
 
WORKDIR /
EXPOSE 8080
COPY --from=dev /hello-api/api /       #8
CMD ["/api"]

The Dockerfile builds the Go binary in a development stage, then copies it into a production stage based on scratch. It keeps the build environment out of the production image. section 7.6

Build and compare two images

Run `docker build -t hello-api:min .` for the production image and `docker build -t hello-api:dev --target dev .` for the development image, then inspect them with `docker images`. In the shown comparison, the development image is 962 MB and the minimal image is 4.74 MB. Treat that difference as a reason to check what each image contains, not as a reason to discard a useful debugging image. section 7.6

Put the build after tests in the delivery pipeline, then push the resulting tags to a registry. Consumers can pull the published image; maintainers can revise the Dockerfile and compare images as their deployment or debugging needs change. section 7.4 section 7.6

How Shipping Go: Develop, deliver, discuss, design, and go again covers it

How deep it goes
Explains images as container templates and layered builds, then works through Buildpack and multi-stage Dockerfile choices without detailing image-format internals.
Examples
Compares tagged Go application images built with a multi-stage Dockerfile and inspected with `docker images`.
What it assumes
Assumes a Go application and an existing test pipeline, while introducing containers and images through a template analogy.
What you can do after
Build it from scratch with a Dockerfile, or apply Buildpacks, then publish the image through a tested pipeline.
How it connects
Connects container images to containers, runtimes, base images, registries, Buildpacks, Dockerfiles, and continuous delivery pipelines.

Also explained in

Compare how 25 books explain container image →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Shipping Go: Develop, deliver, discuss, design, and go again. The section links point to the parts of the book it draws on.