Setting up the initial container
The docker-compose
file will initially just have a go
image and mount our entire local directory. This will allow you to work within the container with all of the application’s source files.
docker-compose.yaml
version: '3'
services:
app:
working_dir: /app
stdin_open: true
image: golang:1.14-alpine
volumes:
- ./:/app
I’ve picked an alpine
build for the go
image because of how small the Alpine images are. It should make the initial builds faster than using larger Linux distributions (and often you won’t need the functionality in said distributions for development or deployment either).
stdin_open
is set to true
so that we can run
$ docker-compose exec app [command]
to execute commands into the container when it is running.
Run:
$ docker-compose up -d
to start the container in detached mode. You can then enter the go
container with:
$ docker-compose run exec app sh
/app #
And you’re in there, capable of running all your Linux commands inside the container!
The app – "Hello, world" revisited
Let us create a simple app – it will just expose a root /
HTTP endpoint which writes Hello, world!
as a response.
main.go
package main
import (
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, world!"))
})
panic(http.ListenAndServe(":8000", nil))
}
The service is exposed on port 8000
for now (we will change this later). We now want to make this exposed in our docker-compose
configuration:
docker-compose.yaml
version: '3'
services:
app:
working_dir: /app
stdin_open: true
image: golang:1.14-alpine
volumes:
- ./:/app
ports:
- 8000:8000
Now run the following commands:
$ docker-compose up -d
$ docker-compose exec app go run main.go
and visit http://localhost:8000 to see the message Hello, world!
. If you see it, congratulations: the app is now containerized! You can stop the container with:
$ docker-compose down
This is a good starting point, but it can be improved on. We want to make the ports configurable for both the host and the container: in a world of microservices development, developers could be running multiple docker containers and apps on various ports, and we want to make this as easy as possible to change.