package main import ( "golang.org/x/net/context" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" "github.com/docker/docker/cli/command" "github.com/docker/docker/client" "fmt" "os" ) var ( err error appName string ) // Keep constants with sensitive information in one place const ( DefaultServer = "registry.gitlab.com" Username = "xxxxx" Password = "xxxxx" ) // App struct holds information about the app that should be launched // with auth and docker client info type App struct { Name string Client *client.Client AuthConfig types.AuthConfig AuthConfigEncoded string Config container.ContainerCreateCreatedBody } func registryAuthentication(image string) types.RequestPrivilegeFunc { return func() (string, error) { authConfig := types.AuthConfig{ Username: Username, Password: Password, ServerAddress: DefaultServer, } base64config, err := command.EncodeAuthToBase64(authConfig) if err != nil { return "", err } return base64config, nil } } // Initialize application from environment variable func (app *App) Initialize() error { app.Client, err = client.NewEnvClient() return err } // Prepare auth registry for usage func (app *App) PrepareRegistry() error { app.AuthConfig = types.AuthConfig{ Username: Username, Password: Password, ServerAddress: DefaultServer, } resp, err := app.Client.RegistryLogin(context.Background(), app.AuthConfig) if err != nil { panic(err) } fmt.Println("Status:\t", resp.Status) if resp.IdentityToken != "" { app.AuthConfig.IdentityToken = resp.IdentityToken } app.AuthConfigEncoded, err = command.EncodeAuthToBase64(app.AuthConfig) return err } func (app *App) ImagePull() error { opts := types.ImagePullOptions{ RegistryAuth: app.AuthConfigEncoded, PrivilegeFunc: registryAuthentication(app.Name), } _, err := app.Client.ImagePull(context.Background(), DefaultServer + "magnus/atom", opts) if err != nil { return err } return nil } func (app *App) ImageIsLoaded() bool { result, err := app.Client.ImageSearch(context.Background(), app.Name, types.ImageSearchOptions{Limit: 1}) if err != nil { panic(err) } if len(result) != 0 { return true } return false } // Create config for container func (app *App) ContainerCreate() error { // Wait for image to be pulled for !app.ImageIsLoaded() { app.Config, err = app.Client.ContainerCreate( context.Background(), &container.Config{Image: app.Name}, &container.HostConfig{}, &network.NetworkingConfig{}, "") return err } return nil } // Launch container with the `App.Name` func (app *App) ContainerStart() error { return app.Client.ContainerStart(context.Background(), app.Config.ID, types.ContainerStartOptions{}) } // Launch app func (app *App) Start() { err = app.Initialize() if err != nil { panic(err) } err = app.PrepareRegistry() if err != nil { panic(err) } err = app.ImagePull() if err != nil { panic(err) } err = app.ContainerCreate() if err != nil { panic(err) } err = app.ContainerStart() if err != nil { panic(err) } } func main() { if len(os.Args) > 1 { appName = os.Args[1] app := App{Name: "magnus/" + appName} app.Start() fmt.Sprintln("Launched", appName) } else { fmt.Println("Please, provide app name") } }