feat: add backup compression
continuous-integration/drone/push Build is passing Details

This commit is contained in:
kolaente 2024-02-13 16:45:10 +01:00
parent 49510a6179
commit 5acf40d86e
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
7 changed files with 54 additions and 9 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
.idea/
docker-db-backup
*.sql
*.gz
./backups

View File

@ -78,6 +78,10 @@ Default: `12`
If provided, the tool will do an empty GET request to this URL to indicate it successfully completed the backup job.
You can use this with other tools to monitor if backups are completed as they should.
### `BACKUP_COMPRESS`
If set provided and set to `true`, all backups will be compressed using gzip.
## Building from source
This project uses go modules, so you'll need at least go 1.11 to compile it.

View File

@ -18,6 +18,7 @@ type conf struct {
Schedule string
MaxBackups int
CompletionWebhookURL string
CompressBackups bool
}
var (
@ -30,6 +31,7 @@ const (
envSchedule = `BACKUP_SCHEDULE`
envMax = `BACKUP_MAX`
envCompletionWebhookURL = `BACKUP_COMPLETION_WEBHOOK_URL`
envCompressBackups = `BACKUP_COMPRESS`
)
func init() {
@ -66,6 +68,11 @@ func init() {
if has {
config.CompletionWebhookURL = webhookURL
}
compress, has := os.LookupEnv(envCompressBackups)
if has {
config.CompressBackups = compress == "1" || compress == "true"
}
}
func updateFullBackupPath() {

View File

@ -63,5 +63,5 @@ func (m *MysqlDumper) Dump(c *client.Client) error {
args := m.buildDumpArgs()
return runAndSaveCommandInContainer(getDumpFilename(m.Container.Name), c, m.Container, "mysqldump", args...)
return runAndSaveCommandInContainer(c, m.Container, "mysqldump", args...)
}

View File

@ -26,5 +26,5 @@ func (d *PostgresDumper) Dump(c *client.Client) error {
user = u
}
return runAndSaveCommandInContainer(getDumpFilename(d.Container.Name), c, d.Container, "pg_dumpall", "-U", user)
return runAndSaveCommandInContainer(c, d.Container, "pg_dumpall", "-U", user)
}

22
go.mod
View File

@ -1,15 +1,31 @@
module kolaente.dev/konrad/docker-db-backup
go 1.16
go 1.21
require (
github.com/containerd/containerd v1.5.5 // indirect
github.com/docker/docker v20.10.8+incompatible
github.com/robfig/cron/v3 v3.0.1
)
require (
github.com/Microsoft/go-winio v0.4.17 // indirect
github.com/containerd/containerd v1.5.5 // indirect
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/robfig/cron/v3 v3.0.1
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect
google.golang.org/grpc v1.40.0 // indirect
google.golang.org/protobuf v1.26.0 // indirect
)

25
save.go
View File

@ -1,6 +1,7 @@
package main
import (
"compress/gzip"
"context"
"fmt"
"io"
@ -10,16 +11,21 @@ import (
"github.com/docker/docker/client"
)
func runAndSaveCommandInContainer(filename string, c *client.Client, container *types.ContainerJSON, command string, args ...string) error {
func runAndSaveCommandInContainer(c *client.Client, container *types.ContainerJSON, command string, args ...string) error {
ctx := context.Background()
config := types.ExecConfig{
filename := getDumpFilename(container.Name)
if config.CompressBackups {
filename += ".gz"
}
containerConfig := types.ExecConfig{
AttachStderr: true,
AttachStdout: true,
Cmd: append([]string{command}, args...),
}
r, err := c.ContainerExecCreate(ctx, container.ID, config)
r, err := c.ContainerExecCreate(ctx, container.ID, containerConfig)
if err != nil {
return err
}
@ -36,7 +42,18 @@ func runAndSaveCommandInContainer(filename string, c *client.Client, container *
}
defer f.Close()
_, err = io.Copy(f, resp.Reader)
var target io.Writer = f
if config.CompressBackups {
gw, err := gzip.NewWriterLevel(f, gzip.BestCompression)
if err != nil {
return err
}
defer gw.Close()
target = gw
}
_, err = io.Copy(target, resp.Reader)
if err != nil {
return err
}