Skip to content

Instantly share code, notes, and snippets.

@lanrat
Created January 19, 2016 19:41
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lanrat/8a8b385959627a7b29f1 to your computer and use it in GitHub Desktop.
Save lanrat/8a8b385959627a7b29f1 to your computer and use it in GitHub Desktop.
Recreate a docker container with the same configuration after an image upgrade
package main
import (
"fmt"
"os"
"strings"
"github.com/fsouza/go-dockerclient"
//"github.com/tonnerre/golang-pretty"
)
func check(err error) {
if err != nil {
fmt.Println(err)
os.Exit(0)
}
}
func main() {
if len(os.Args) != 2 {
fmt.Printf("Usage: %s [Container ID]\n", os.Args[0])
os.Exit(0)
}
/*
also have option to build locally, or retirieve docker file and built rather than pull
Steps:
* Pull new if from remote
* Save old config
* Make new container
* Rename old
* stop old if started
* start new if old is running
* option: delete old if sucsessfull
* if error rename old to origional name, and put back in origional state
*/
endpoint := "unix:///var/run/docker.sock"
client, _ := docker.NewClient(endpoint)
// get container info
old_container, err := client.InspectContainer(os.Args[1])
check(err)
//TODO delete _new if an error occores
// pull new image
//TODO
// also need to ensure we use the latest version of the iamge when building?
// TODO check to make sure rebuilt container is using updated image
fmt.Printf("Image: %s\n", old_container.Config.Image)
// get image data
//TODO handle image tags/labels?
// naming
name := old_container.Name
tmp_name := name+"_new"
// copy container
var options docker.CreateContainerOptions
options.Name = tmp_name
options.Config = old_container.Config
options.HostConfig = old_container.HostConfig
// get all vomumes
//options.HostConfig.VolumesFrom = append(options.HostConfig.VolumesFrom, old_container.ID)
options.HostConfig.VolumesFrom = []string{old_container.ID}
// get all links
// this is a hack to fix the way links are returned and sent
links := old_container.HostConfig.Links
for i := range links {
parts := strings.SplitN(links[i], ":", 2)
if len(parts) != 2 {
fmt.Println("Unable to parse link ", links[i])
// TODO make function and add better error return
return
}
container_name := strings.TrimPrefix(parts[0], "/")
alias_parts := strings.Split(parts[1], "/")
alias := alias_parts[len(alias_parts)-1]
links[i] = fmt.Sprintf("%s:%s", container_name, alias)
}
options.HostConfig.Links = links
fmt.Println("Creating...")
new_container, err := client.CreateContainer(options)
check(err)
// rename
err = client.RenameContainer(docker.RenameContainerOptions{ID:old_container.ID, Name:name+"_old"})
check(err)
err = client.RenameContainer(docker.RenameContainerOptions{ID:new_container.ID, Name:name})
check(err)
if old_container.State.Running {
fmt.Printf("Stopping old container\n")
err = client.StopContainer(old_container.ID, 10)
check(err)
fmt.Printf("Starting new container\n")
err = client.StartContainer(new_container.ID, new_container.HostConfig)
check(err)
}
// add optionn to rm old container on sucsess
fmt.Printf("Migrated from %s to %s\n", old_container.ID, new_container.ID)
fmt.Println("Done")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment