This post is going to describe how to build applications using the BusyBox docker image, along with a sample web server that we will run using BusyBox as the base.
You can see the sample code for this post on Github
What Is BusyBox?
From it’s own webpage:
BusyBox combines tiny versions of many common UNIX utilities into a single small executable.
The BusyBox Docker container gives us an image many times smaller than, for example, the Ubuntu image:
➜ ~ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 34378e11e069 7 days ago 1.4MB
ubuntu latest 58810d071ecb 4 weeks ago 65.6MB
This lets us create our own images with a much smaller footprint if we use BusyBox as the base.
This is especially useful when you want to optimize overall resources on your system, or if you’re using a system with limited disk space.
Creating a BusyBox Container
To run an interactive shell on a BusyBox container, we can execute this command:
docker run -it --rm busybox
We can then run common commands on the shell. For example, let’s list all the commands that are available to us:
/ #
/ # ls /bin
[ ifdown rm
[[ ifenslave rmdir
acpid ifplugd rmmod
add-shell ifup route
...
...
Running Custom Executable Files
Since BusyBox gives us a basic Linux environment, we can compile programs to run on Linux and create custom executables using BusyBox as the base.
For example, let’s create a simple “hello world” program using Go (Golang).
First, we can create a directory on our machine. Within the directory, we’ll create a Dockerfile
and main.go
file:
.
├── Dockerfile
└── main.go
Our main.go
file contains a simple program to print “hello world” to the console:
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
If you’ve installed Go, you can compile the above program:
GOOS=linux GOARCH=amd64 go build main.go
This should output a file called main
.
GOOS
and GOARCH
specify the target system that we want to compile for. In this case, BusyBox runs Linux OS with the “amd64” architecture.
Because we’re compiling for BusyBox, the compiled file may not work on your own machine. To run this on your own machine, you can execute
go build main.go
without theGOOS
andGOARCH
variables
Creating Our Docker Image
We can add commands to our Dockerfile
to run the compiled program:
# Use busybox as the base image
FROM busybox
# Copy over the executable file
COPY ./main /home/
# Run the executable file
CMD /home/main
We can create the image by running:
docker build -t hello-world .
This will create the new hello-world
image, which we can now run by executing:
docker run --rm hello-world
Once the container has been run, you can see the output on your terminal:
hello world
What’s more, the total size of the hello-world
image is only around 3.3MB:
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 3b0d3ab8c11f 3 minutes ago 3.34MB
Running an HTTP Web Server
Let’s add a new file called server.go
in the same directory. Here, we’ll create a simple HTTP server that runs on port 8080
responds to every request with the text "Hello World!"
:
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!")
}
func main() {
http.HandleFunc("/", handler)
fmt.Println("Server running...")
http.ListenAndServe(":8080", nil)
}
Compile the program:
GOOS=linux GOARCH=amd64 go build server.go
Now, the executable file name will be server
. We can modify the Dockerfile
to use this instead:
FROM busybox
COPY ./server /home/
CMD /home/server
Build the Dockerfile
with a new image tag:
docker build -t go-server .
Create and run new container from your image by running :
docker run -p 8080:8080 --rm -it go-server
The
-p 8080:8080
forwards the8080
port from the container to your local machine
You can send a curl request to http://localhost:8080/
, or even visit it on your browser:
curl -v http://localhost:8080/
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sat, 28 Aug 2021 09:31:38 GMT
< Content-Length: 12
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host localhost left intact
Hello World!
The total size of the Docker image is around 7MB:
REPOSITORY TAG IMAGE ID CREATED SIZE
go-server latest e5b1fb0caa64 52 seconds ago 7.53MB
We have now successfully created and run an HTTP web application in Docker using BusyBox.
You can see the sample code for this post on Github
Have you ever used BusyBox to run your application? How was your experience? Let me know in the comments!