Documentation
¶
Overview ¶
Package dockerlocation moves Docker's data, and containerd's where Docker keeps its images there (the containerd image store, Docker 29's default), to another folder. The folders Docker and containerd use stay where they are: /var/lib/docker and /var/lib/containerd become bind mounts of the new folder's docker and containerd folders, systemd mount units that the two services require. Neither service's configuration is touched.
A move goes from the default place to a folder, or back: never from one folder to another, which would go through the default place anyway. It stops Docker, copies, switches the mounts, checks that the live folders are the new copy, starts Docker again and checks that what ran before runs again; anything wrong puts everything back as it was, and says where the data is when it could not. The old data is kept until the owner deletes it. A move cut short by a stop of this service is finished or undone at its next start (Recover).
Index ¶
Constants ¶
const ( PhaseIdle = "idle" PhaseStopping = "stopping" PhaseCopying = "copying" PhaseSwitching = "switching" PhaseStarting = "starting" PhaseDone = "done" PhaseFailed = "failed" // nothing changed, or everything was put back )
Phases of a move, as the dashboard shows them.
const ( Default = "" DefaultDir = "/var/lib/docker" )
Default is the target that puts Docker's data back in its default place, DefaultDir; a check of it reports DefaultDir as its path.
Variables ¶
var Roots = []string{"/DATA", "/media"}
Roots may hold Docker's data: the data folder and the drives mounted under /media.
Functions ¶
func MountUnit ¶
MountUnit is the systemd unit binding what onto where, after the folder's own mount.
func ParseProgress ¶
ParseProgress reads the bytes copied from a line of rsync --info=progress2.
Types ¶
type Check ¶
type Check struct {
Path string `json:"path"`
FSType string `json:"fs_type"`
FreeBytes int64 `json:"free_bytes"`
NeedBytes int64 `json:"need_bytes"`
OK bool `json:"ok"`
Reason string `json:"reason,omitempty"`
Location string `json:"location"`
UsedBytes int64 `json:"used_bytes"`
Containers int `json:"containers"`
}
Check says whether a folder can take Docker's data.
type Mover ¶
type Mover struct {
// Root prefixes every host path; empty on a real host, a folder in tests.
Root string
// StatePath is where State is kept across restarts.
StatePath string
// Run runs a command; tests replace it.
Run func(ctx context.Context, name string, args ...string) (string, error)
// StatFS says a folder's file system and free space; tests replace it.
StatFS func(path string) (fsType string, freeBytes int64, err error)
// Copy copies a live folder into its new place; tests replace it.
Copy func(ctx context.Context, src, dst string) error
// SameDir says whether two paths are the same folder (a bind mount shows
// its source's device and inode); tests replace it.
SameDir func(a, b string) bool
// Wait is how long Docker and the containers get to come back after a
// switch, Poll how often they are asked; zero: 2 minutes, 2 seconds.
Wait, Poll time.Duration
// contains filtered or unexported fields
}
Mover runs one move at a time and remembers where the data is.
func (*Mover) CheckTarget ¶
CheckTarget says whether path can take the data now in its place. It asks Docker where its data is, and measures it at most every usageFresh: the move measures again before it stops anything.
func (*Mover) DeleteOldCopy ¶
DeleteOldCopy deletes what the last move left behind. Each folder is looked at first: never one Docker uses, whatever the list says.
func (*Mover) Recover ¶
Recover deals with a move a stop of this service cut short (an update, a crash, the machine turned off), at the next start:
- stopped or copying: nothing was switched; the partial copy goes and Docker starts again with the containers that ran;
- switching: the switch is put back to where the data was, which the move never touched;
- starting: the switch was done; Docker and the containers are started.
Docker is never left stopped by an interrupted move.
type State ¶
type State struct {
Phase string `json:"phase"`
Message string `json:"message,omitempty"`
Location string `json:"location"` // the folder holding docker/ and containerd/; empty: the default place
Target string `json:"target,omitempty"`
TotalBytes int64 `json:"total_bytes,omitempty"`
CopiedBytes int64 `json:"copied_bytes,omitempty"`
OldCopy []string `json:"old_copy,omitempty"` // what the last move left behind, to delete
StartedAt *time.Time `json:"started_at,omitempty"`
FinishedAt *time.Time `json:"finished_at,omitempty"`
// kept for Recover while a move runs: where it went from, and the
// containers to start again
From string `json:"from,omitempty"`
Running []string `json:"running,omitempty"`
// how many images Docker had before the move, checked again by Recover
// on a switch it keeps
Images int `json:"images,omitempty"`
// set once a failed switch or start is being undone: a stop then leaves a
// switch that may look complete, and must be undone, never kept
Undoing bool `json:"undoing,omitempty"`
}
State is where Docker's data is, and the move under way or the last one.