Here is a sample custom integration of Golang with Docker:
Creating a Dockerfile for Your Golang Application
1. Dockerfile:
dockerfile
# Use the official Golang image
FROM golang:1.19
# Set the working directory in the container
WORKDIR /app
# Copy the Go module file
COPY go.mod go.sum ./
# Download dependencies
RUN go mod download
# Copy the application code
COPY *.go ./
# Build the application
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/main
# Expose the port
EXPOSE 8080
# Define the command to run when the container starts
CMD ["/app/main"]
2. Building and Running the Docker Container:
bash
# Build the Docker image
docker build -t my-golang-app-image .
# Run a container from the image
docker run -p 303080 -it --rm --name my-golang-app-run my-golang-app-image
Using Docker Compose for Orchestration
1. docker-compose.yml:
yaml
version: '2'
services:
my-golang-app-run:
container_name: my-golang-app-run
build: .
command: go run main.go
volumes:
- ./src:/go/src/app
working_dir: /go/src/app
ports:
- "303080"
environment:
PORT: 8080
2. Running the Docker Compose File:
bash
docker-compose up
Why Use Docker Locally?
Using Docker locally allows you to avoid cluttering your local environment with various runtimes. This approach is beneficial when working on multiple projects with different runtimes[1][2][3].
Example of Using Dockertest for Integration Tests
1. dockertest_test.go:
go
package dockertest_test
import (
"database/sql"
"fmt"
"log"
"os"
"testing"
_ "github.com/go-sql-driver/mysql"
"github.com/ory/dockertest/v3"
)
var db *sql.DB
func TestMain(m *testing.M) {
// Create a Docker pool
pool, err := dockertest.NewPool("")
if err != nil {
log.Fatalf("Could not construct pool: %s", err)
}
// Connect to Docker
err = pool.Client.Ping()
if err != nil {
log.Fatalf("Could not connect to Docker: %s", err)
}
// Run a MySQL container
resource, err := pool.Run("mysql", "5.7", []string{"MYSQL_ROOT_PASSWORD=secret"})
if err != nil {
log.Fatalf("Could not start resource: %s", err)
}
// Connect to the MySQL database
if err := pool.Retry(func() error {
var err error
db, err = sql.Open("mysql", fmt.Sprintf("root:secret@(localhost:%s)/mysql", resource.GetPort("3306/tcp")))
if err != nil {
return err
}
return db.Ping()
}); err != nil {
log.Fatalf("Could not connect to database: %s", err)
}
// Run the tests
code := m.Run()
// Purge the resource
if err := pool.Purge(resource); err != nil {
log.Fatalf("Could not purge resource: %s", err)
}
}
2. Running the Tests Using GitHub Actions:
yaml
name: Test with Docker on
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
services:
dind:
image: docker:23.0-rc-dind-rootless
ports:
- 2375:2375
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.19
- name: Run tests
run: go test -v ./...
This example demonstrates how to integrate Golang with Docker for building and running a Docker container, using Docker Compose for orchestration, and utilizing Dockertest for integration tests.
Citations:[1] https://golang.withcodeexample.com/blog/go-app-deployment-docker-guide/
[2] https://docs.docker.com/language/golang/build-images/
[3] https://www.docker.com/blog/developing-go-apps-docker/
[4] https://github.com/ory/dockertest
[5] https://www.ardanlabs.com/blog/2019/03/integration-testing-in-go-executing-tests-with-docker.html