WIP
- commit
- 383266cf8d42a32094f481d8a6df9231e4dc9484
- author
- bnema · · 2023-09-06 18:53 UTC
- parent
- a921f70
- signature
- unsigned
4 files · +85 -21
R pkg/docker/registry.go → pkg/docker/commands.go +39 -9 renamed, 76% similar
| @@ -5,14 +5,12 @@ import ( | |||
| 5 | 5 | "fmt" | |
| 6 | 6 | "io" | |
| 7 | 7 | "os" | |
| 8 | - | "os/exec" | |
| 9 | 8 | ||
| 10 | 9 | "github.com/docker/docker/api/types" | |
| 11 | 10 | "github.com/docker/docker/api/types/container" | |
| 12 | 11 | "github.com/docker/docker/client" | |
| 13 | 12 | "github.com/docker/docker/pkg/archive" | |
| 14 | 13 | "github.com/docker/docker/pkg/stdcopy" | |
| 15 | - | "gogs.bnema.dev/gordon-echo/pkg/utils" | |
| 16 | 14 | ) | |
| 17 | 15 | ||
| 18 | 16 | func DockertPullImageTest() { | |
| @@ -128,13 +126,45 @@ func CreateImageFromDockerfile() { | |||
| 128 | 126 | } | |
| 129 | 127 | } | |
| 130 | 128 | ||
| 131 | - | func RunCommand(command string, arg string, logger *utils.Logger) error { | |
| 132 | - | cmd := exec.Command(command, arg) | |
| 133 | - | cmd.Stdout = logger | |
| 134 | - | cmd.Stderr = logger | |
| 135 | - | err := cmd.Run() | |
| 129 | + | // Check if a network exists | |
| 130 | + | func NetworkExists(name string) (bool, error) { | |
| 131 | + | fmt.Println("Initialized Docker client.") | |
| 132 | + | ctx := context.Background() | |
| 133 | + | cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) | |
| 134 | + | if err != nil { | |
| 135 | + | panic(err) | |
| 136 | + | } | |
| 137 | + | defer cli.Close() | |
| 138 | + | ||
| 139 | + | fmt.Println("Checking if network exists...") | |
| 140 | + | networks, err := cli.NetworkList(ctx, types.NetworkListOptions{}) | |
| 141 | + | if err != nil { | |
| 142 | + | panic(err) | |
| 143 | + | } | |
| 144 | + | ||
| 145 | + | for _, network := range networks { | |
| 146 | + | if network.Name == name { | |
| 147 | + | return true | |
| 148 | + | } | |
| 149 | + | } | |
| 150 | + | ||
| 151 | + | return false, nil | |
| 152 | + | } | |
| 153 | + | ||
| 154 | + | // Create network as a bridge | |
| 155 | + | func CreateNetwork(name string) error | |
| 156 | + | ctx := context.Background() | |
| 157 | + | cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) | |
| 136 | 158 | if err != nil { | |
| 137 | - | return err | |
| 159 | + | panic(err) | |
| 160 | + | } | |
| 161 | + | defer cli.Close() | |
| 162 | + | ||
| 163 | + | fmt.Println("Creating network...") | |
| 164 | + | _, err = cli.NetworkCreate(ctx, name, types.NetworkCreate{ | |
| 165 | + | Driver: "bridge", | |
| 166 | + | }) | |
| 167 | + | if err != nil { | |
| 168 | + | panic(err) | |
| 138 | 169 | } | |
| 139 | - | return nil | |
| 140 | 170 | } | |
| @@ -5,14 +5,12 @@ import ( | |||||
| 5 | "fmt" | 5 | "fmt" | ||
| 6 | "io" | 6 | "io" | ||
| 7 | "os" | 7 | "os" | ||
| 8 | - | "os/exec" | |||
| 9 | 8 | ||||
| 10 | "github.com/docker/docker/api/types" | 9 | "github.com/docker/docker/api/types" | ||
| 11 | "github.com/docker/docker/api/types/container" | 10 | "github.com/docker/docker/api/types/container" | ||
| 12 | "github.com/docker/docker/client" | 11 | "github.com/docker/docker/client" | ||
| 13 | "github.com/docker/docker/pkg/archive" | 12 | "github.com/docker/docker/pkg/archive" | ||
| 14 | "github.com/docker/docker/pkg/stdcopy" | 13 | "github.com/docker/docker/pkg/stdcopy" | ||
| 15 | - | "gogs.bnema.dev/gordon-echo/pkg/utils" | |||
| 16 | ) | 14 | ) | ||
| 17 | 15 | ||||
| 18 | func DockertPullImageTest() { | 16 | func DockertPullImageTest() { | ||
| @@ -128,13 +126,45 @@ func CreateImageFromDockerfile() { | |||||
| 128 | } | 126 | } | ||
| 129 | } | 127 | } | ||
| 130 | 128 | ||||
| 131 | - | func RunCommand(command string, arg string, logger *utils.Logger) error { | 129 | + | // Check if a network exists |
| 132 | - | cmd := exec.Command(command, arg) | 130 | + | func NetworkExists(name string) (bool, error) { |
| 133 | - | cmd.Stdout = logger | 131 | + | fmt.Println("Initialized Docker client.") |
| 134 | - | cmd.Stderr = logger | 132 | + | ctx := context.Background() |
| 135 | - | err := cmd.Run() | 133 | + | cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) |
| 134 | + | if err != nil { | |||
| 135 | + | panic(err) | |||
| 136 | + | } | |||
| 137 | + | defer cli.Close() | |||
| 138 | + | ||||
| 139 | + | fmt.Println("Checking if network exists...") | |||
| 140 | + | networks, err := cli.NetworkList(ctx, types.NetworkListOptions{}) | |||
| 141 | + | if err != nil { | |||
| 142 | + | panic(err) | |||
| 143 | + | } | |||
| 144 | + | ||||
| 145 | + | for _, network := range networks { | |||
| 146 | + | if network.Name == name { | |||
| 147 | + | return true | |||
| 148 | + | } | |||
| 149 | + | } | |||
| 150 | + | ||||
| 151 | + | return false, nil | |||
| 152 | + | } | |||
| 153 | + | ||||
| 154 | + | // Create network as a bridge | |||
| 155 | + | func CreateNetwork(name string) error | |||
| 156 | + | ctx := context.Background() | |||
| 157 | + | cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) | |||
| 136 | if err != nil { | 158 | if err != nil { | ||
| 137 | - | return err | 159 | + | panic(err) |
| 160 | + | } | |||
| 161 | + | defer cli.Close() | |||
| 162 | + | ||||
| 163 | + | fmt.Println("Creating network...") | |||
| 164 | + | _, err = cli.NetworkCreate(ctx, name, types.NetworkCreate{ | |||
| 165 | + | Driver: "bridge", | |||
| 166 | + | }) | |||
| 167 | + | if err != nil { | |||
| 168 | + | panic(err) | |||
| 138 | } | 169 | } | ||
| 139 | - | return nil | |||
| 140 | } | 170 | } | ||
M pkg/scripts/install-traefik.go +31 -8
| @@ -7,10 +7,17 @@ import ( | |||
| 7 | 7 | ||
| 8 | 8 | root "gogs.bnema.dev/gordon-echo" | |
| 9 | 9 | "gogs.bnema.dev/gordon-echo/internal/app" | |
| 10 | + | "gogs.bnema.dev/gordon-echo/pkg/docker" | |
| 10 | 11 | "gogs.bnema.dev/gordon-echo/pkg/templating" | |
| 11 | 12 | "gogs.bnema.dev/gordon-echo/pkg/utils" | |
| 12 | 13 | ) | |
| 13 | 14 | ||
| 15 | + | func ensureDirExists(dir string) error { | |
| 16 | + | if _, err := os.Stat(dir); os.IsNotExist(err) { | |
| 17 | + | return os.Mkdir(dir, 0755) | |
| 18 | + | } | |
| 19 | + | return nil | |
| 20 | + | } | |
| 14 | 21 | func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |
| 15 | 22 | path := app.GetBuildDir() + "/" | |
| 16 | 23 | modelFS := root.ModelFS | |
| @@ -19,11 +26,12 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||
| 19 | 26 | } | |
| 20 | 27 | ||
| 21 | 28 | // Check if directory traefik exists, if not create it | |
| 22 | - | if _, err := os.Stat(path + "traefik"); os.IsNotExist(err) { | |
| 23 | - | err = os.Mkdir(path+"traefik", 0755) | |
| 24 | - | if err != nil { | |
| 25 | - | return err | |
| 26 | - | } | |
| 29 | + | if err := ensureDirExists(path + "traefik"); err != nil { | |
| 30 | + | return err | |
| 31 | + | } | |
| 32 | + | // Check if directory traefik/volume exists, if not create it | |
| 33 | + | if err := ensureDirExists(path + "traefik/volume"); err != nil { | |
| 34 | + | return err | |
| 27 | 35 | } | |
| 28 | 36 | ||
| 29 | 37 | // Setup the TXT renderer for traefik-compose.goyml | |
| @@ -42,7 +50,7 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||
| 42 | 50 | return err | |
| 43 | 51 | } | |
| 44 | 52 | // Save the rendered content to a file at the env path | |
| 45 | - | err = os.WriteFile(path+"docker-compose.yml", []byte(composeContent), 0644) | |
| 53 | + | err = os.WriteFile(path+"traefik/docker-compose.yml", []byte(composeContent), 0644) | |
| 46 | 54 | if err != nil { | |
| 47 | 55 | return err | |
| 48 | 56 | } | |
| @@ -53,7 +61,7 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||
| 53 | 61 | return err | |
| 54 | 62 | } | |
| 55 | 63 | ||
| 56 | - | // Render the traefik.goyml with payload data | |
| 64 | + | // Render the traefik.goyml with payload | |
| 57 | 65 | traefikContent, err := rendererTraefik.TXTRender(map[string]string{ | |
| 58 | 66 | "admin.email": adminEmail, | |
| 59 | 67 | }) | |
| @@ -67,6 +75,21 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||
| 67 | 75 | return err | |
| 68 | 76 | } | |
| 69 | 77 | ||
| 70 | - | return nil | |
| 78 | + | // Now that we have the YAML files, we can launch the containers | |
| 79 | + | // Create acme.json with permissions 600 | |
| 80 | + | if f, err := os.Create(path + "traefik/volume/acme.json"); err != nil { | |
| 81 | + | return err | |
| 82 | + | } else if err = f.Chmod(0600); err != nil { | |
| 83 | + | return err | |
| 84 | + | } else { | |
| 85 | + | f.Close() // Schedule closing of the file when function exits | |
| 86 | + | } | |
| 87 | + | ||
| 88 | + | // Create the network "exposed" if it doesn't exist | |
| 89 | + | // Ensure that the network "exposed" exists if not create it | |
| 90 | + | exists, err := docker.NetworkExists("exposed") | |
| 91 | + | if err != nil { | |
| 92 | + | // handle the error | |
| 93 | + | } | |
| 71 | 94 | ||
| 72 | 95 | } | |
| @@ -7,10 +7,17 @@ import ( | |||||
| 7 | 7 | ||||
| 8 | root "gogs.bnema.dev/gordon-echo" | 8 | root "gogs.bnema.dev/gordon-echo" | ||
| 9 | "gogs.bnema.dev/gordon-echo/internal/app" | 9 | "gogs.bnema.dev/gordon-echo/internal/app" | ||
| 10 | + | "gogs.bnema.dev/gordon-echo/pkg/docker" | |||
| 10 | "gogs.bnema.dev/gordon-echo/pkg/templating" | 11 | "gogs.bnema.dev/gordon-echo/pkg/templating" | ||
| 11 | "gogs.bnema.dev/gordon-echo/pkg/utils" | 12 | "gogs.bnema.dev/gordon-echo/pkg/utils" | ||
| 12 | ) | 13 | ) | ||
| 13 | 14 | ||||
| 15 | + | func ensureDirExists(dir string) error { | |||
| 16 | + | if _, err := os.Stat(dir); os.IsNotExist(err) { | |||
| 17 | + | return os.Mkdir(dir, 0755) | |||
| 18 | + | } | |||
| 19 | + | return nil | |||
| 20 | + | } | |||
| 14 | func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | 21 | func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | ||
| 15 | path := app.GetBuildDir() + "/" | 22 | path := app.GetBuildDir() + "/" | ||
| 16 | modelFS := root.ModelFS | 23 | modelFS := root.ModelFS | ||
| @@ -19,11 +26,12 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||||
| 19 | } | 26 | } | ||
| 20 | 27 | ||||
| 21 | // Check if directory traefik exists, if not create it | 28 | // Check if directory traefik exists, if not create it | ||
| 22 | - | if _, err := os.Stat(path + "traefik"); os.IsNotExist(err) { | 29 | + | if err := ensureDirExists(path + "traefik"); err != nil { |
| 23 | - | err = os.Mkdir(path+"traefik", 0755) | 30 | + | return err |
| 24 | - | if err != nil { | 31 | + | } |
| 25 | - | return err | 32 | + | // Check if directory traefik/volume exists, if not create it |
| 26 | - | } | 33 | + | if err := ensureDirExists(path + "traefik/volume"); err != nil { |
| 34 | + | return err | |||
| 27 | } | 35 | } | ||
| 28 | 36 | ||||
| 29 | // Setup the TXT renderer for traefik-compose.goyml | 37 | // Setup the TXT renderer for traefik-compose.goyml | ||
| @@ -42,7 +50,7 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||||
| 42 | return err | 50 | return err | ||
| 43 | } | 51 | } | ||
| 44 | // Save the rendered content to a file at the env path | 52 | // Save the rendered content to a file at the env path | ||
| 45 | - | err = os.WriteFile(path+"docker-compose.yml", []byte(composeContent), 0644) | 53 | + | err = os.WriteFile(path+"traefik/docker-compose.yml", []byte(composeContent), 0644) |
| 46 | if err != nil { | 54 | if err != nil { | ||
| 47 | return err | 55 | return err | ||
| 48 | } | 56 | } | ||
| @@ -53,7 +61,7 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||||
| 53 | return err | 61 | return err | ||
| 54 | } | 62 | } | ||
| 55 | 63 | ||||
| 56 | - | // Render the traefik.goyml with payload data | 64 | + | // Render the traefik.goyml with payload |
| 57 | traefikContent, err := rendererTraefik.TXTRender(map[string]string{ | 65 | traefikContent, err := rendererTraefik.TXTRender(map[string]string{ | ||
| 58 | "admin.email": adminEmail, | 66 | "admin.email": adminEmail, | ||
| 59 | }) | 67 | }) | ||
| @@ -67,6 +75,21 @@ func CreateYAMLFiles(topDomain, adminEmail string, logger *utils.Logger) error { | |||||
| 67 | return err | 75 | return err | ||
| 68 | } | 76 | } | ||
| 69 | 77 | ||||
| 70 | - | return nil | 78 | + | // Now that we have the YAML files, we can launch the containers |
| 79 | + | // Create acme.json with permissions 600 | |||
| 80 | + | if f, err := os.Create(path + "traefik/volume/acme.json"); err != nil { | |||
| 81 | + | return err | |||
| 82 | + | } else if err = f.Chmod(0600); err != nil { | |||
| 83 | + | return err | |||
| 84 | + | } else { | |||
| 85 | + | f.Close() // Schedule closing of the file when function exits | |||
| 86 | + | } | |||
| 87 | + | ||||
| 88 | + | // Create the network "exposed" if it doesn't exist | |||
| 89 | + | // Ensure that the network "exposed" exists if not create it | |||
| 90 | + | exists, err := docker.NetworkExists("exposed") | |||
| 91 | + | if err != nil { | |||
| 92 | + | // handle the error | |||
| 93 | + | } | |||
| 71 | 94 | ||||
| 72 | } | 95 | } | ||
M pkg/templating/models/traefik-compose.goyml +10 -3
| @@ -2,7 +2,7 @@ version: "3" | |||
| 2 | 2 | ||
| 3 | 3 | services: | |
| 4 | 4 | traefik: | |
| 5 | - | image: traefik:v2.10.4 | |
| 5 | + | image: traefik:v2.10 | |
| 6 | 6 | container_name: traefik | |
| 7 | 7 | restart: unless-stopped | |
| 8 | 8 | ports: | |
| @@ -10,8 +10,9 @@ services: | |||
| 10 | 10 | - "443:443" | |
| 11 | 11 | volumes: | |
| 12 | 12 | - /var/run/docker.sock:/var/run/docker.sock:ro | |
| 13 | - | - /home/brice/traefik/data/traefik.yml:/etc/traefik/traefik.yml | |
| 14 | - | - /home/brice/traefik/data/acme.json:/acme.json | |
| 13 | + | - traefik.yml:/etc/traefik/traefik.yml | |
| 14 | + | - traefik/volume/acme.json:/acme.json | |
| 15 | + | - traefik/volume/traefik.log:/var/log/traefik/traefik.log | |
| 15 | 16 | labels: | |
| 16 | 17 | - "traefik.enable=true" | |
| 17 | 18 | - "traefik.http.routers.api.rule=Host(`traefik.{{ .topdomain }}`)" | |
| @@ -19,3 +20,9 @@ services: | |||
| 19 | 20 | - "traefik.http.routers.api.entrypoints=websecure" | |
| 20 | 21 | - "traefik.http.routers.api.tls.certresolver=myresolver" | |
| 21 | 22 | - "traefik.http.services.api.loadbalancer.server.port=8080" | |
| 23 | + | networks: | |
| 24 | + | - exposed | |
| 25 | + | ||
| 26 | + | networks: | |
| 27 | + | exposed: | |
| 28 | + | external: true⏎̸ | |
| @@ -2,7 +2,7 @@ version: "3" | |||||
| 2 | 2 | ||||
| 3 | services: | 3 | services: | ||
| 4 | traefik: | 4 | traefik: | ||
| 5 | - | image: traefik:v2.10.4 | 5 | + | image: traefik:v2.10 |
| 6 | container_name: traefik | 6 | container_name: traefik | ||
| 7 | restart: unless-stopped | 7 | restart: unless-stopped | ||
| 8 | ports: | 8 | ports: | ||
| @@ -10,8 +10,9 @@ services: | |||||
| 10 | - "443:443" | 10 | - "443:443" | ||
| 11 | volumes: | 11 | volumes: | ||
| 12 | - /var/run/docker.sock:/var/run/docker.sock:ro | 12 | - /var/run/docker.sock:/var/run/docker.sock:ro | ||
| 13 | - | - /home/brice/traefik/data/traefik.yml:/etc/traefik/traefik.yml | 13 | + | - traefik.yml:/etc/traefik/traefik.yml |
| 14 | - | - /home/brice/traefik/data/acme.json:/acme.json | 14 | + | - traefik/volume/acme.json:/acme.json |
| 15 | + | - traefik/volume/traefik.log:/var/log/traefik/traefik.log | |||
| 15 | labels: | 16 | labels: | ||
| 16 | - "traefik.enable=true" | 17 | - "traefik.enable=true" | ||
| 17 | - "traefik.http.routers.api.rule=Host(`traefik.{{ .topdomain }}`)" | 18 | - "traefik.http.routers.api.rule=Host(`traefik.{{ .topdomain }}`)" | ||
| @@ -19,3 +20,9 @@ services: | |||||
| 19 | - "traefik.http.routers.api.entrypoints=websecure" | 20 | - "traefik.http.routers.api.entrypoints=websecure" | ||
| 20 | - "traefik.http.routers.api.tls.certresolver=myresolver" | 21 | - "traefik.http.routers.api.tls.certresolver=myresolver" | ||
| 21 | - "traefik.http.services.api.loadbalancer.server.port=8080" | 22 | - "traefik.http.services.api.loadbalancer.server.port=8080" | ||
| 23 | + | networks: | |||
| 24 | + | - exposed | |||
| 25 | + | ||||
| 26 | + | networks: | |||
| 27 | + | exposed: | |||
| 28 | + | external: true⏎̸ | |||
M pkg/templating/models/traefik.goyml +5 -1
| @@ -1,5 +1,5 @@ | |||
| 1 | 1 | api: | |
| 2 | - | dashboard: true | |
| 2 | + | dashboard: false | |
| 3 | 3 | ||
| 4 | 4 | entryPoints: | |
| 5 | 5 | web: | |
| @@ -22,5 +22,9 @@ certificatesResolvers: | |||
| 22 | 22 | ||
| 23 | 23 | log: | |
| 24 | 24 | level: "DEBUG" # Set the desired log level: DEBUG, INFO, WARN, ERROR, FATAL, PANIC | |
| 25 | + | filePath: "/var/log/traefik/traefik.log" | |
| 25 | 26 | ||
| 26 | 27 | accessLog: {} | |
| 28 | + | ||
| 29 | + | ping: | |
| 30 | + | entryPoint: web ⏎̸ | |
| @@ -1,5 +1,5 @@ | |||||
| 1 | api: | 1 | api: | ||
| 2 | - | dashboard: true | 2 | + | dashboard: false |
| 3 | 3 | ||||
| 4 | entryPoints: | 4 | entryPoints: | ||
| 5 | web: | 5 | web: | ||
| @@ -22,5 +22,9 @@ certificatesResolvers: | |||||
| 22 | 22 | ||||
| 23 | log: | 23 | log: | ||
| 24 | level: "DEBUG" # Set the desired log level: DEBUG, INFO, WARN, ERROR, FATAL, PANIC | 24 | level: "DEBUG" # Set the desired log level: DEBUG, INFO, WARN, ERROR, FATAL, PANIC | ||
| 25 | + | filePath: "/var/log/traefik/traefik.log" | |||
| 25 | 26 | ||||
| 26 | accessLog: {} | 27 | accessLog: {} | ||
| 28 | + | ||||
| 29 | + | ping: | |||
| 30 | + | entryPoint: web ⏎̸ | |||