> ## Documentation Index
> Fetch the complete documentation index at: https://docs.minimus.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Slim Down an App Using a Runtime Base

> How to build more secure apps using multi-stage builds with a runtime base image

Some images will allow you to separate the build stages such that you can compile the app with one image and then copy the final binary onto a minimal runtime base image such as [static](https://images.minimus.io/gallery/images/static) or [glibc-dynamic](https://images.minimus.io/gallery/images/glibc-dynamic) to significantly reduce the size of the final container image. This technique produces images that are ultra-light, hardened, performant, and secure.

## Example with Go

Go is a great test case to demonstrate the value of using a multi-stage build to slim down the final app. Go is a compiled language that is not optimized for use as a runtime. For this reason, it is recommended to use a multi-stage build. We will compile the binary using the Go image, then copy the binary into a minimal runtime base image.

Knowing which runtime base image to use depends on how your Go project was compiled:

* If compiled as a static app, use the [static Go image](https://images.minimus.io/gallery/images/go).
* If compiled as a dynamically linked app, use the [Glibc-Dynamic image](https://images.minimus.io/gallery/images/glibc-dynamic).

## Static runtime

### About static Go applications

Static binaries are self-contained and do not rely on shared system libraries or runtime dependencies on the host system. As such, they are fully portable and avoid compatibility issues with C libraries. If the static Go binary is mounted on a static base image, it will produce a tiny image, that is as minimal as it gets.

In the example below, the flag `CGO_ENABLED=0` is added to the Dockerfile to ensure that the compiled binary is statically linked. CGO is a Go tool that enables the creation of Go packages that call C code. When CGO is disabled, the resulting binary is statically linked.

### Example

1. Authenticate to the Minimus registry. [Learn more](/manage/token)
2. In your project directory, save the code below to a Dockerfile:

   ```dockerfile Dockerfile example expandable lines theme={null}
   # Pull Go image and set it as builder
   FROM reg.mini.dev/go:latest AS builder

   # Set CGO_ENABLED to 0 to create a static binary
   ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64

   # Copy project directory content to app directory in the container
   COPY . /app

   # Compile your Go app
   RUN cd /app && go build -o go-minimus .

   # Pull static image to use as a runtime base image
   FROM reg.mini.dev/static:latest

   # Copy go-minimus binary from the /app directory in the builder container to /usr/bin/ in the final static container
   COPY --from=builder /app/go-minimus /usr/bin/

   # Set the container entrypoint to run the go-minimus binary when the container is started
   ENTRYPOINT ["/usr/bin/go-minimus"]
   ```
3. In your project directory, save the code below to a file and name it `hello-minimus.go`.

   This is a very simple script which prints "Hello from Minimus!" to the terminal. You can use your own script instead.

   ```
   package main

   import "fmt"

   func main() {
       fmt.Println("Hello from Minimus!")
   }
   ```
4. In your project directory, create a `go.mod` file. This file declares the modules and dependencies required by the project. In our case, the module set is only needed for testing purposes, so it's very simple.

   ```
   module minimus.dev/hello_minimus

   go 1.19
   ```
5. Your project directory should now contain 3 files:
   1. `Dockerfile`
   2. `hello-minimus.go`
   3. `go.mod`
6. From your project directory run the following command to build the custom image `hello-go`:

   ```
   docker build -t hello-go .
   ```

   <Info>
     The period `.` specifies the current directory as the build context.
   </Info>
7. Spin up the image just created with this command:

   ```
   docker run hello-go
   ```

## Dynamic runtime

### About dynamic Go applications

If your Go app needs to link to database drivers or other C integrations, you can compile a dynamically linked binary by setting the `CGO_ENABLED=1` flag. Make sure the required C libraries are available in both your build and runtime environments.

In the example below, we will use the Minimus Glibc-Dynamic image as a runtime base for a simple web application.

### Example

1. Authenticate to the Minimus registry. [Learn more](/manage/token)
2. In a new project directory, save the code below to a new Dockerfile:

   ```docker Dockerfile example expandable lines theme={null}
   # Pull Go image and set it as builder
   FROM reg.mini.dev/go AS builder

   # Set CGO_ENABLED=1 to compile a dynamically linked binary
   ENV CGO_ENABLED=1 GOOS=linux GOARCH=amd64

   # Copy the project directory content to app directory in the container
   COPY . /app

   # Compile Go application
   RUN cd /app && go build -o Hello-Minimus-Web .

   # Pull dynamic image to use as a runtime base
   FROM reg.mini.dev/glibc-dynamic:latest

   # Copy Go binary from the /app directory in the builder container to /usr/bin/ in the final dynamic container
   COPY --from=builder /app/Hello-Minimus-Web /usr/bin/

   EXPOSE 8080

   # Set entrypoint to run the binary when the container is started
   ENTRYPOINT ["/usr/bin/Hello-Minimus-Web"]
   ```
3. [Download the example file](https://github.com/minimusio/examples/blob/main/golang/hello-minimus-web.go) `hello-minimus-web.go` and save it to your project directory. This is a very simple script that creates a webpage with several tabs so you can navigate between them.
4. In your project directory, create a `go.mod` file. This file declares the modules and dependencies required by the project. In our case, the module set is only needed for testing purposes, so it's very simple.

   ```
   module minimus.dev/hello_minimus

   go 1.19
   ```
5. Your project directory should now contain 3 files:
   1. `Dockerfile`
   2. `hello-minimus-web.go`
   3. `go.mod`
6. From your project directory run the following command to build the image:

   ```bash theme={null}
   docker build -t hello-go-web .
   ```

   <Info>
     The period `.` specifies the current directory as the build context.
   </Info>
7. Spin up the image we just created with this command:

   ```bash theme={null}
   docker run -p 8080:8080 hello-go-web
   ```
8. Open your browser and go to [http://localhost:8080/](http://localhost:8080/) to see the default welcome page.
