Compare commits

...

6 Commits

Author SHA1 Message Date
Frederik Ring
c391230be6 Merge pull request #31 from offen/exclude-symlink-candidates
Exclude symlinks from candidates when pruning local files
2021-10-31 20:07:51 +01:00
Frederik Ring
f946f36fb0 exclude symlinks from candidates when pruning local files
Previously, symlinks would be included in the set of candidates, but would
be skipped when pruning. This could lead to a wrong number of candidates
being printed in the log messages.
2021-10-29 09:00:37 +02:00
Frederik Ring
5245b5882f update README, save some indentation 2021-10-28 19:55:39 +02:00
schwannden
7f0f173115 adding option to skip tls verification error (#30)
* adding option to skip tls verification error

* merge options

* removed merged option from README

Co-authored-by: Schwannden Kuo <schwannden@mobagel.com>
2021-10-28 19:51:35 +02:00
Frederik Ring
ad7ec58322 add syntax highlighting 2021-10-23 17:45:57 +02:00
Frederik Ring
b7ab2fbacc add section about container timezones to the README 2021-10-23 17:44:30 +02:00
2 changed files with 61 additions and 11 deletions

View File

@@ -17,6 +17,7 @@ It handles __recurring or one-off backups of Docker volumes__ to a __local direc
- [Send email notifications on failed backup runs](#send-email-notifications-on-failed-backup-runs) - [Send email notifications on failed backup runs](#send-email-notifications-on-failed-backup-runs)
- [Encrypting your backup using GPG](#encrypting-your-backup-using-gpg) - [Encrypting your backup using GPG](#encrypting-your-backup-using-gpg)
- [Restoring a volume from a backup](#restoring-a-volume-from-a-backup) - [Restoring a volume from a backup](#restoring-a-volume-from-a-backup)
- [Set the timezone the container runs in](#set-the-timezone-the-container-runs-in)
- [Using with Docker Swarm](#using-with-docker-swarm) - [Using with Docker Swarm](#using-with-docker-swarm)
- [Manually triggering a backup](#manually-triggering-a-backup) - [Manually triggering a backup](#manually-triggering-a-backup)
- [Recipes](#recipes) - [Recipes](#recipes)
@@ -161,7 +162,8 @@ You can populate below template according to your requirements and use it as you
# Setting this variable to `true` will disable verification of # Setting this variable to `true` will disable verification of
# SSL certificates. You shouldn't use this unless you use self-signed # SSL certificates. You shouldn't use this unless you use self-signed
# certificates for your remote storage backend. # certificates for your remote storage backend. This can only be used
# when AWS_ENDPOINT_PROTO is set to `https`.
# AWS_ENDPOINT_INSECURE="true" # AWS_ENDPOINT_INSECURE="true"
@@ -358,6 +360,27 @@ In case you need to restore a volume from a backup, the most straight forward pr
Depending on your setup and the application(s) you are running, this might involve other steps to be taken still. Depending on your setup and the application(s) you are running, this might involve other steps to be taken still.
### Set the timezone the container runs in
By default a container based on this image will run in the UTC timezone.
As the image is designed to be as small as possible, additional timezone data is not included.
In case you want to run your cron rules in your local timezone (respecting DST and similar), you can mount your Docker host's `/etc/timezone` and `/etc/localtime` in read-only mode:
```yml
version: '3'
services:
backup:
image: offen/docker-volume-backup:latest
volumes:
- data:/backup/my-app-backup:ro
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
volumes:
data:
```
### Using with Docker Swarm ### Using with Docker Swarm
By default, Docker Swarm will restart stopped containers automatically, even when manually stopped. By default, Docker Swarm will restart stopped containers automatically, even when manually stopped.
@@ -593,3 +616,5 @@ Local copies of backups can also be pruned once they reach a certain age.
- InfluxDB specific functionality from the original image was removed. - InfluxDB specific functionality from the original image was removed.
- `arm64` and `arm/v7` architectures are supported. - `arm64` and `arm/v7` architectures are supported.
- Docker in Swarm mode is supported. - Docker in Swarm mode is supported.
- Notifications on failed backups are supported
- IAM authentication through instance profiles is supported

View File

@@ -160,10 +160,25 @@ func newScript() (*script, error) {
return nil, errors.New("newScript: AWS_S3_BUCKET_NAME is defined, but no credentials were provided") return nil, errors.New("newScript: AWS_S3_BUCKET_NAME is defined, but no credentials were provided")
} }
mc, err := minio.New(s.c.AwsEndpoint, &minio.Options{ options := minio.Options{
Creds: creds, Creds: creds,
Secure: !s.c.AwsEndpointInsecure && s.c.AwsEndpointProto == "https", Secure: s.c.AwsEndpointProto == "https",
}) }
if s.c.AwsEndpointInsecure {
if !options.Secure {
return nil, errors.New("newScript: AWS_ENDPOINT_INSECURE = true is only meaningful for https")
}
transport, err := minio.DefaultTransport(true)
if err != nil {
return nil, fmt.Errorf("newScript: failed to create default minio transport")
}
transport.TLSClientConfig.InsecureSkipVerify = true
options.Transport = transport
}
mc, err := minio.New(s.c.AwsEndpoint, &options)
if err != nil { if err != nil {
return nil, fmt.Errorf("newScript: error setting up minio client: %w", err) return nil, fmt.Errorf("newScript: error setting up minio client: %w", err)
} }
@@ -488,17 +503,21 @@ func (s *script) pruneOldBackups() error {
} }
if _, err := os.Stat(s.c.BackupArchive); !os.IsNotExist(err) { if _, err := os.Stat(s.c.BackupArchive); !os.IsNotExist(err) {
candidates, err := filepath.Glob( globPattern := path.Join(
path.Join(s.c.BackupArchive, fmt.Sprintf("%s*", s.c.BackupPruningPrefix)), s.c.BackupArchive,
fmt.Sprintf("%s*", s.c.BackupPruningPrefix),
) )
globMatches, err := filepath.Glob(globPattern)
if err != nil { if err != nil {
return fmt.Errorf( return fmt.Errorf(
"pruneOldBackups: error looking up matching files, starting with: %w", err, "pruneOldBackups: error looking up matching files using pattern %s: %w",
globPattern,
err,
) )
} }
var matches []string var candidates []os.FileInfo
for _, candidate := range candidates { for _, candidate := range globMatches {
fi, err := os.Stat(candidate) fi, err := os.Stat(candidate)
if err != nil { if err != nil {
return fmt.Errorf( return fmt.Errorf(
@@ -507,8 +526,14 @@ func (s *script) pruneOldBackups() error {
err, err,
) )
} }
if fi.Mode() != os.ModeSymlink {
candidates = append(candidates, fi)
}
}
if fi.Mode() != os.ModeSymlink && fi.ModTime().Before(deadline) { var matches []os.FileInfo
for _, candidate := range candidates {
if candidate.ModTime().Before(deadline) {
matches = append(matches, candidate) matches = append(matches, candidate)
} }
} }
@@ -516,7 +541,7 @@ func (s *script) pruneOldBackups() error {
if len(matches) != 0 && len(matches) != len(candidates) { if len(matches) != 0 && len(matches) != len(candidates) {
var removeErrors []error var removeErrors []error
for _, candidate := range matches { for _, candidate := range matches {
if err := os.Remove(candidate); err != nil { if err := os.Remove(candidate.Name()); err != nil {
removeErrors = append(removeErrors, err) removeErrors = append(removeErrors, err)
} }
} }