Skip to content

Instantly share code, notes, and snippets.

@shayne
Created June 2, 2018 04:07
Show Gist options
  • Save shayne/c7f4314e280f926b9b61d5ad3a4c6a83 to your computer and use it in GitHub Desktop.
Save shayne/c7f4314e280f926b9b61d5ad3a4c6a83 to your computer and use it in GitHub Desktop.
Holdup
package main
import (
"context"
"fmt"
"io/ioutil"
"log"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/client"
)
func main() {
// check if volume /test is mounted by listing directory (should see at least one file)
files, err := ioutil.ReadDir("/test")
if err != nil {
time.Sleep(time.Second * 10)
log.Fatal(err)
} else if len(files) == 0 {
time.Sleep(time.Second * 10)
log.Fatal("No files found in /test, must not be mounted")
}
// if we get here then we have /test and it sees files
// which means that the mount is ready
log.Println("Found files in /test... continuing to the docker restart step")
// query exited containers and issue restart
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
args := filters.NewArgs()
args.Add("status", "exited")
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{Filters: args})
if err != nil {
panic(err)
}
duration := time.Second * 10
fmt.Println("Restarting containers...")
for _, container := range containers {
fmt.Printf("%s %s\n", container.ID[:10], container.Image)
err := cli.ContainerRestart(context.Background(), container.ID, &duration)
if err != nil {
log.Printf("Failed to restart container: %s - %s\n", container.Image, err)
}
}
}
@SerdarSanri
Copy link

I found an issue using this and wondering if any workaround. So I have few containers based on mysql, php and nodejs, and I was having problems when computer rebooted. Most of the time volumes are not ready and I lose dbs and files unless I restart each container. with your script it worked auto-magically. But after using a while I noticed an odd behavior. One of my docker containers has websockets in it. on the client side every minute I see a connection lost message then comes back. When I compare the timestamps it looks like when holdup container kicks in it stops the container then restarts. Is there any way to limit this process ( restating holdup container for checking volumes ready ) until it finds a file. then it restarts all containers and stop itself.

current situation is even thou it finds files and restarts, it continues restarting containers every 60 secs.

@shayne
Copy link
Author

shayne commented Feb 22, 2019

Can you check the container logs for holdup?... on like 46 it prints what container it's restarting. Also Line 37 filters only exited status containers.

In order to have holdup auto-start when docker is started the restart policy of always is suggested. This means it will run on start then exit and should no-op for the rest of the system on time. If a container stops randomly it will restart it. So in your case, if the container running websockets is stopping the holdup will restart it.

Another idea is that you have a stopped/exited container that might interfere with the websockets container? When things are running run docker ps -a --filter status=exited and see what results you have. Perhaps there's an extraneous container.

@ChuckyNorris
Copy link

Hi Shayne

I'm trying to get this to work on my Raspberry Pi running LibreElec.
I'm getting the error: standard_init_linux.go:178: exec user process caused "exec format error".
Any idea what I might need to do get it working?

Thanks
Charles

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment