Skip to content

Commit

Permalink
docker: use docker-ce packages (#884)
Browse files Browse the repository at this point in the history
  • Loading branch information
abiosoft authored Nov 18, 2023
1 parent a9df8ba commit 4304114
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 40 deletions.
7 changes: 6 additions & 1 deletion environment/container/containerd/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,19 @@ func (c containerdRuntime) Name() string {
}

func (c containerdRuntime) Provision(context.Context) error {
if err := c.guest.RunQuiet("sh", "-c",
`sudo sed -i '/disabled_plugins =/c\disabled_plugins = []' /etc/containerd/config.toml`,
); err != nil {
return err
}
return c.guest.Write(buildKitConfFile, buildKitConf)
}

func (c containerdRuntime) Start(ctx context.Context) error {
a := c.Init(ctx)

a.Add(func() error {
return c.guest.Run("sudo", "service", "containerd", "start")
return c.guest.Run("sudo", "service", "containerd", "restart")
})

// service startup takes few seconds, retry at most 10 times before giving up.
Expand Down
6 changes: 4 additions & 2 deletions environment/container/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ func (d dockerRuntime) Provision(ctx context.Context) error {
func (d dockerRuntime) Start(ctx context.Context) error {
a := d.Init(ctx)

a.Add(func() error {
return d.guest.Run("sudo", "service", "docker", "start")
// TODO: interval is high due to 0.6.3->0.6.4 docker-ce package transition
// to ensure startup is successful
a.Retry("", time.Second*5, 24, func(int) error {
return d.guest.RunQuiet("sudo", "service", "docker", "start")
})

// service startup takes few seconds, retry at most 5 times before giving up.
Expand Down
24 changes: 24 additions & 0 deletions environment/vm/lima/deb/deb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package deb

import (
"github.com/abiosoft/colima/environment"
)

type (
hostActions = environment.HostActions
guestActions = environment.GuestActions
)

// URISource is the source for fetching URI for deb packages.
type URISource interface {
// Name is the name for the URISource.
Name() string
// Packages is the list of package names.
Packages() []string
// URIs return the list of URIs to download the deb files.
URIs(arch environment.Arch) ([]string, error)
// PreInstall is done before the deb package are installed.
PreInstall() error
// Install installs the packages directly using the internet.
Install() error
}
77 changes: 77 additions & 0 deletions environment/vm/lima/deb/docker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package deb

import (
"fmt"
"strings"

"github.com/abiosoft/colima/environment"
)

var dockerPackages = []string{
"docker-ce",
"docker-ce-cli",
"containerd.io",
"docker-buildx-plugin",
"docker-compose-plugin",
}

var _ URISource = (*Docker)(nil)

// Docker is the URISource for Docker CE packages.
type Docker struct {
Host hostActions
Guest guestActions
}

// PreInstall implements URISource.
func (d *Docker) PreInstall() error {
return d.Guest.RunQuiet("sh", "-c", "sudo apt remove -y docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc")
}

// Install implements URISource.
func (d *Docker) Install() error {
return d.Guest.Run("sh", "-c",
`curl -fsSL https://get.docker.com -o /tmp/get-docker.sh && sudo sh /tmp/get-docker.sh`,
)
}

// Name implements URISource.
func (*Docker) Name() string {
return "docker-ce"
}

// Packages implements URISource.
func (*Docker) Packages() []string {
return dockerPackages
}

// URIs implements URISource.
func (d *Docker) URIs(arch environment.Arch) ([]string, error) {
var uris []string

pkgFiles, err := d.pkgFiles(arch)
if err != nil {
return nil, fmt.Errorf("error getting package names and version: %w", err)
}

for _, file := range pkgFiles {
uri := d.debPackageBaseURI(arch) + file
uris = append(uris, uri)
}

return uris, nil
}

func (d Docker) pkgFiles(arch environment.Arch) ([]string, error) {
script := fmt.Sprintf(`curl -sL https://download.docker.com/linux/ubuntu/dists/mantic/stable/binary-%s/Packages | grep '^Filename: ' | awk -F'/' '{print $NF}'`, arch.Value().GoArch())
filenames, err := d.Host.RunOutput("sh", "-c", script)
if err != nil {
return nil, fmt.Errorf("error retrieving deb package filenames: %w", err)
}

return strings.Fields(filenames), nil
}

func (d Docker) debPackageBaseURI(arch environment.Arch) string {
return fmt.Sprintf("https://download.docker.com/linux/ubuntu/dists/mantic/pool/stable/%s/", arch.GoArch())
}
61 changes: 61 additions & 0 deletions environment/vm/lima/deb/mantic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package deb

import (
"fmt"
"strings"

"github.com/abiosoft/colima/environment"
)

var manticPackages = []string{
// docker
"iptables",
// k8s
"socat",
// utilities
"htop", "vim", "inetutils-ping", "dnsutils",
}

var _ URISource = (*Mantic)(nil)

// Mantic is the URISource for Ubuntu Mantic packages.
type Mantic struct {
Guest guestActions
}

// PreInstall implements URISource.
func (*Mantic) PreInstall() error {
return nil
}

// Packages implements URISource.
func (*Mantic) Packages() []string {
return manticPackages
}

// Name implements URISource.
func (*Mantic) Name() string {
return "mantic-debs"
}

// URIs implements URISource.
func (m *Mantic) URIs(_ environment.Arch) ([]string, error) {
_ = m.Guest.RunQuiet("sudo apt update -y")

output := ""
for _, p := range manticPackages {
line := fmt.Sprintf(`sudo apt-get install --reinstall --print-uris -qq "%s" | cut -d"'" -f2`, p)
out, err := m.Guest.RunOutput("sh", "-c", line)
if err != nil {
return nil, fmt.Errorf("error fetching dependencies list: %w", err)
}
output += out + " "
}

return strings.Fields(output), nil
}

// Install implements URISource.
func (m *Mantic) Install() error {
return m.Guest.Run("sh", "-c", "sudo apt update && sudo apt install -f -y "+strings.Join(manticPackages, " "))
}
89 changes: 52 additions & 37 deletions environment/vm/lima/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,25 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/environment/vm/lima/deb"
"github.com/abiosoft/colima/util/fsutil"
"github.com/abiosoft/colima/util/terminal"
"github.com/sirupsen/logrus"
)

var dependencyPackages = []string{
// docker and k8s
"docker.io", "socat",
// utilities
"htop", "vim", "inetutils-ping", "dnsutils",
}

// cacheDependencies downloads the ubuntu deb files to a path on the host.
// The return value is the directory of the downloaded deb files.
func (l *limaVM) cacheDependencies(log *logrus.Entry, conf config.Config) (string, error) {
func (l *limaVM) cacheDependencies(src deb.URISource, log *logrus.Entry, conf config.Config) (string, error) {
codename, err := l.RunOutput("sh", "-c", `grep "^UBUNTU_CODENAME" /etc/os-release | cut -d= -f2`)
if err != nil {
return "", fmt.Errorf("error retrieving OS version from vm: %w", err)
}

arch := environment.Arch(conf.Arch).Value()
dir := filepath.Join(config.CacheDir(), "packages", codename, string(arch))
dir := filepath.Join(config.CacheDir(), "packages", codename, string(arch), src.Name())
if err := fsutil.MkdirAll(dir, 0755); err != nil {
return "", fmt.Errorf("error creating cache directory for OS packages: %w", err)
}
Expand All @@ -40,17 +33,12 @@ func (l *limaVM) cacheDependencies(log *logrus.Entry, conf config.Config) (strin
return dir, nil
}

output := ""
for _, p := range dependencyPackages {
line := fmt.Sprintf(`sudo apt-get install --reinstall --print-uris -qq "%s" | cut -d"'" -f2`, p)
out, err := l.RunOutput("sh", "-c", line)
if err != nil {
return "", fmt.Errorf("error fetching dependencies list: %w", err)
}
output += out + " "
var debPackages []string
packages, err := src.URIs(arch)
if err != nil {
return "", fmt.Errorf("error fetching package URIs using %s: %w", src.Name(), err)
}

debPackages := strings.Fields(output)
debPackages = append(debPackages, packages...)

// progress bar for Ubuntu deb packages download.
// TODO: extract this into re-usable progress bar for multi-downloads
Expand All @@ -76,27 +64,54 @@ func (l *limaVM) cacheDependencies(log *logrus.Entry, conf config.Config) (strin
}

func (l *limaVM) installDependencies(log *logrus.Entry, conf config.Config) error {
// cache dependencies
dir, err := l.cacheDependencies(log, conf)
if err != nil {
log.Warnln(fmt.Errorf("error caching dependencies: %w", err))
log.Warnln("falling back to normal package install")
return l.Run("sh", "-c", "sudo apt install -y "+strings.Join(dependencyPackages, " "))
srcs := []deb.URISource{
&deb.Mantic{Guest: l},
&deb.Docker{Host: l.host, Guest: l},
}

// validate if packages were previously installed
installed := true
for _, p := range dependencyPackages {
if err := l.RunQuiet("dpkg", "-s", p); err != nil {
installed = false
break
for _, src := range srcs {
if err := src.PreInstall(); err != nil {
log.Warn(fmt.Errorf("preinstall check failed for %s: %w", src.Name(), err))
}

// cache dependencies
dir, err := l.cacheDependencies(src, log, conf)
if err != nil {
log.Warnln(fmt.Errorf("error caching dependencies for %s: %w", src.Name(), err))
log.Warnln("falling back to normal package install")

if err := src.Install(); err != nil {
return fmt.Errorf("error installing packages using %s: %w", src.Name(), err)
}

// installed
continue
}

// validate if packages were previously installed
installed := true
for _, p := range src.Packages() {
if err := l.RunQuiet("dpkg", "-s", p); err != nil {
installed = false
break
}
}

if installed {
continue
}

// install packages
if err := l.Run("sh", "-c", "sudo dpkg -i "+dir+"/*.deb"); err != nil {
log.Warn(fmt.Errorf("error installing packages using %s: %w", src.Name(), err))
log.Warnln("falling back to normal package install")

if err := src.Install(); err != nil {
return fmt.Errorf("error installing packages using %s: %w", src.Name(), err)
}
}
}

if installed {
return nil
}

// install packages
return l.Run("sh", "-c", "sudo dpkg -i "+dir+"/*.deb")
return nil
}

0 comments on commit 4304114

Please sign in to comment.