func StartOrCreate(ctx context.Context, docker client.CommonAPIClient, networkID string, db config.Database, output terminal.Outputer) (string, string, error) {
	filter := filters.NewArgs()
	filter.Add("label", containerlabels.DatabaseEngine+"="+db.Engine)
	filter.Add("label", containerlabels.DatabaseVersion+"="+db.Version)
	filter.Add("label", containerlabels.DatabasePort+"="+db.Port)
	filter.Add("label", containerlabels.Type+"=database")
	hostname, err := db.GetHostname()
	if err != nil {
		return "", "", err
	}
	if db.Engine == "mariadb" || db.Engine == "mysql" {
		filter.Add("label", containerlabels.DatabaseCompatibility+"=mysql")
	} else {
		filter.Add("label", containerlabels.DatabaseCompatibility+"=postgres")
	}
	containers, err := docker.ContainerList(ctx, types.ContainerListOptions{All: true, Filters: filter})
	if err != nil {
		return "", "", fmt.Errorf("error getting a list of containers")
	}
	if len(containers) == 1 {
		if containers[0].State != "running" {
			if err := docker.ContainerStart(ctx, containers[0].ID, types.ContainerStartOptions{}); err != nil {
				return "", "", err
			}
		}
		return containers[0].ID, hostname, nil
	}
	labels := map[string]string{
		containerlabels.Nitro:           "true",
		containerlabels.DatabaseEngine:  db.Engine,
		containerlabels.DatabaseVersion: db.Version,
		containerlabels.Type:            "database",
		containerlabels.DatabasePort:    db.Port,
	}
	if db.Engine == "mariadb" || db.Engine == "mysql" {
		labels[containerlabels.DatabaseCompatibility] = "mysql"
	}
	if db.Engine == "postgres" {
		labels[containerlabels.DatabaseCompatibility] = "postgres"
	}
	volume, err := docker.VolumeCreate(ctx, volumetypes.VolumeCreateBody{Driver: "local", Name: hostname, Labels: labels})
	if err != nil {
		return "", "", fmt.Errorf("unable to create the volume, %w", err)
	}
	image := fmt.Sprintf(DatabaseImage, db.Engine, db.Version)
	target := "/var/lib/mysql"
	var envs []string
	if strings.Contains(image, "postgres") {
		target = "/var/lib/postgresql/data"
		envs = []string{"POSTGRES_USER=nitro", "POSTGRES_DB=nitro", "POSTGRES_PASSWORD=nitro"}
	} else {
		envs = []string{"MYSQL_ROOT_PASSWORD=nitro", "MYSQL_DATABASE=nitro", "MYSQL_USER=nitro", "MYSQL_PASSWORD=nitro"}
	}
	imageFilter := filters.NewArgs()
	imageFilter.Add("reference", image)
	images, err := docker.ImageList(ctx, types.ImageListOptions{Filters: imageFilter, All: true})
	if err != nil {
		return "", "", fmt.Errorf("unable to get a list of images, %w", err)
	}
	if len(images) == 0 {
		output.Pending("downloading", image)
		rdr, err := docker.ImagePull(ctx, image, types.ImagePullOptions{All: false})
		if err != nil {
			output.Warning()
			return "", "", fmt.Errorf("unable to pull image %s, %w", image, err)
		}
		buf := &bytes.Buffer{}
		if _, err := buf.ReadFrom(rdr); err != nil {
			output.Warning()
			return "", "", fmt.Errorf("unable to read output from pulling image %s, %w", image, err)
		}
	}
	var port nat.Port
	switch db.Engine {
	case "postgres":
		port, err = nat.NewPort("tcp", "5432")
		if err != nil {
			return "", "", fmt.Errorf("unable to create the port, %w", err)
		}
	default:
		port, err = nat.NewPort("tcp", "3306")
		if err != nil {
			return "", "", fmt.Errorf("unable to create the port, %w", err)
		}
	}
	containerConfig := &container.Config{
		Image:  image,
		Labels: labels,
		ExposedPorts: nat.PortSet{
			port: struct{}{},
		},
		Env: envs,
	}
	if db.Engine == "mysql" {
		containerConfig.Cmd = []string{"--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"}
	}
	hostConfig := &container.HostConfig{
		CapAdd: []string{"SYS_NICE"},
		Mounts: []mount.Mount{
			{
				Type:   mount.TypeVolume,
				Source: volume.Name,
				Target: target,
			},
		},
		PortBindings: map[nat.Port][]nat.PortBinding{
			port: {
				{
					HostIP:   "127.0.0.1",
					HostPort: db.Port,
				},
			},
		},
	}
	networkConfig := &network.NetworkingConfig{
		EndpointsConfig: map[string]*network.EndpointSettings{
			"nitro-network": {
				NetworkID: networkID,
			},
		},
	}
	resp, err := docker.ContainerCreate(ctx, containerConfig, hostConfig, networkConfig, nil, hostname)
	if err != nil {
		return "", "", fmt.Errorf("unable to create the container, %w", err)
	}
	if err := docker.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
		return "", "", fmt.Errorf("unable to start the container, %w", err)
	}
	if db.Engine == "mysql" || db.Engine == "mariadb" {
		if err := waitForMySQLContainer(ctx, docker, resp.ID, db); err != nil {
			return "", "", err
		}
	}
	return resp.ID, hostname, nil
}
StartOrCreate is used to find a specific database and start the container. If there is no container for the database,
it will create a new volume and container for the database.
package databasecontainer
import (
	"bytes"
	"context"
	"database/sql"
	"fmt"
	"strings"
	"time"
	"github.com/craftcms/nitro/pkg/config"
	"github.com/craftcms/nitro/pkg/containerlabels"
	"github.com/craftcms/nitro/pkg/terminal"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/mount"
	"github.com/docker/docker/api/types/network"
	volumetypes "github.com/docker/docker/api/types/volume"
	"github.com/docker/docker/client"
	"github.com/docker/go-connections/nat"
	_ "github.com/go-sql-driver/mysql"
)
var (
	DatabaseImage = "%s:%s"
)