Running Docker container using Golang
Imports
import (
"context"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
Pull image function
func pullImage(ctx context.Context, cli *client.Client, imageId string) error {
r, err := cli.ImagePull(ctx, imageId, types.ImagePullOptions{
Platform: "linux/amd64",
})
if err != nil {
return err
}
defer r.Close()
return nil
}
Create container function
func createContainer(ctx context.Context, cli *client.Client, imageId string, containerPort string, targetPort string, containerName string) (container.CreateResponse, error) {
resp, err := cli.ContainerCreate(
ctx,
&container.Config{
Image: imageId,
ExposedPorts: nat.PortSet{nat.Port(containerPort): struct{}{}},
},
&container.HostConfig{
PortBindings: map[nat.Port][]nat.PortBinding{
nat.Port(containerPort): {{HostIP: "0.0.0.0", HostPort: targetPort}}},
},
nil,
&v1.Platform{},
containerName,
)
return resp, err
}
Run container
func main() {
containerName := "my_app"
imageId := "my_image:1.0"
containerPort := "8080"
targetPort := "8080"
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
panic(err)
}
cli.NegotiateAPIVersion(ctx)
err = pullImage(ctx, cli, imageId)
if err != nil {
panic(err)
}
resp, err := createContainer(ctx, cli, imageId, containerPort, targetPort, containerName)
if err != nil {
panic(err)
}
err = cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
if err != nil {
panic(err)
}
}
Bonus function: Get random available port
func getRandomAvailablePort() (string, error) {
l, err := net.Listen("tcp", "localhost:0")
if err != nil {
return "0", err
}
defer l.Close()
addr := l.Addr().(*net.TCPAddr)
return fmt.Sprintf("%d", addr.Port), nil
}