feat: add backup compression
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
49510a6179
commit
5acf40d86e
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
.idea/
|
||||
docker-db-backup
|
||||
*.sql
|
||||
*.gz
|
||||
./backups
|
||||
|
@ -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.
|
||||
|
@ -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() {
|
||||
|
@ -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...)
|
||||
}
|
||||
|
@ -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
22
go.mod
@ -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
25
save.go
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user