diff --git a/README.md b/README.md
index cc4f43f86..f1d38a121 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Container runtimes on macOS (and Linux) with minimal setup.
### Installation
-Colima is available on Homebrew, MacPorts, and Nix. Check [here](INSTALL.md) for other installation options.
+Colima is available on Homebrew, MacPorts, and Nix. Check [here](docs/INSTALL.md) for other installation options.
```
# Homebrew
@@ -141,105 +141,9 @@ Colima means Containers in [Lima](https://github.com/lima-vm/lima).
Since Lima is aka Linux on Mac. By transitivity, Colima can also mean Containers on Linux on Mac.
-## FAQ
+## FAQs
-
-How does Colima compare to Lima?
-
-
-Colima is basically a higher level usage of Lima and utilises Lima to provide Docker, Containerd and/or Kubernetes.
-
-If you want more control over the underlying VM, you can either use Lima directly or override Colima's VM settings with [Lima overrides](https://github.com/lima-vm/lima/blob/873a39c6652fe5fcb07ee08418f39ccaeeea6979/pkg/limayaml/default.yaml#L271).
-
-
-
-
-
-Can it run alongside Docker for Mac?
-
-Yes, from version v0.3.0 Colima leverages Docker contexts and can thereby run alongside Docker for Mac.
-
-`docker context list` can list all contexts and `docker context use` can be used to change the active context.
-
-
-
-
-
-How to customize Docker config e.g. add insecure registries?
-
-
-### v0.3.4 or older
-
-On first startup, Colima generates Docker daemon.json file at `$HOME/.colima/docker/daemon.json`.
-
-Simply modify the daemon.json file accordingly and restart Colima.
-
-### v0.4.0 or newer
-
-Start Colima with `--edit` flag `colima start --edit` and add the config to the `docker` section.
-
-To manually modify the config file, it is located at `$HOME/.colima/default/colima.yaml` for the default profile,
-, `$HOME/.colima//colima.yaml` for other profiles, and `$HOME/.colima/_templates/default.yaml` for the default
-template.
-
-
-
-
-
-How does it compare to minikube, Kind, K3d?
-
-
-### For Kubernetes
-
-Yes, you can create a Kubernetes cluster with minikube (with Docker driver), Kind or K3d instead of enabling Kubernetes
-in Colima. Those are better options if you need multiple clusters, or do not need Docker and Kubernetes to share the
-same images and runtime.
-
-### For Docker
-
-Minikube with Docker runtime can expose the cluster's Docker with `minikube docker-env`. But there are some caveats.
-
-- Kubernetes is not optional, even if you only need Docker.
-
-- All of minikube's free drivers for macOS fall-short in one of performance, port forwarding or volumes. While
- port-forwarding and volumes are non-issue for Kubernetes, they can be a deal breaker for Docker-only use.
-
-### Compatibility
-
-Colima with Docker runtime is compatible with Kind and K3d.
-
-
-
-
-
-Are M1 macs supported?
-
-
-Colima supports and works on M1 macs but not rigorously tested as the author do not currently possess an M1 device.
-Feedbacks would be appreciated.
-
-
-
-
-
-Can I set default configurations?
-
-
-Yes, via the `template` command.
-
-```
-colima template
-```
-
-Use a preferred editor by setting `$EDITOR` or passing the `--editor` flag
-
-```sh
-colima start --edit --editor code # one-off edit
-colima template --editor code # set the default config
-```
-
-
-
+Check [here](docs/FAQ.md) for Frequently Asked Questions.
## Help Wanted
diff --git a/cmd/nerdctl.go b/cmd/nerdctl.go
index dd44bf08f..2185723fd 100644
--- a/cmd/nerdctl.go
+++ b/cmd/nerdctl.go
@@ -97,7 +97,7 @@ var nerdctlLinkFunc = func() *cobra.Command {
Profile string
}{
ColimaApp: os.Args[0],
- Profile: strings.TrimPrefix(config.Profile().ID, "colima-"),
+ Profile: config.Profile().ShortName,
}
var buf bytes.Buffer
if err := t.Execute(&buf, values); err != nil {
@@ -112,6 +112,9 @@ var nerdctlLinkFunc = func() *cobra.Command {
return fmt.Errorf("error backing up existing file: %w", err)
}
}
+ if err := os.MkdirAll("/usr/local/bin", 0755); err != nil {
+ return nil
+ }
return os.WriteFile(nerdctlCmdArgs.path, buf.Bytes(), 0755)
}
@@ -123,6 +126,14 @@ var nerdctlLinkFunc = func() *cobra.Command {
return fmt.Errorf("error backing up existing file: %w", err)
}
}
+ // prepare dir
+ {
+ c := cli.CommandInteractive("sudo", "mkdir", "-p", "/usr/local/bin")
+ if err := c.Run(); err != nil {
+ return err
+ }
+ }
+ // install script
{
c := cli.CommandInteractive("sudo", "sh", "-c", "cat > "+nerdctlCmdArgs.path)
c.Stdin = &buf
diff --git a/cmd/ssh-config.go b/cmd/ssh-config.go
index dd90b1159..bbbf7647d 100644
--- a/cmd/ssh-config.go
+++ b/cmd/ssh-config.go
@@ -33,5 +33,5 @@ func init() {
root.Cmd().AddCommand(sshConfigCmd)
sshConfigCmd.Flags().StringVarP(&sshConfigCmdArgs.format, "format", "f", "config", "format (config, cmd)")
- sshConfigCmd.Flags().BoolVarP(&sshCmdArgs.layer, "layer", "l", true, "config for the Ubuntu layer (if enabled)")
+ sshConfigCmd.Flags().BoolVarP(&sshConfigCmdArgs.layer, "layer", "l", true, "config for the Ubuntu layer (if enabled)")
}
diff --git a/docs/FAQ.md b/docs/FAQ.md
new file mode 100644
index 000000000..d2bbeed16
--- /dev/null
+++ b/docs/FAQ.md
@@ -0,0 +1,257 @@
+# FAQs
+
+- [FAQs](#faqs)
+ - [How does Colima compare to Lima?](#how-does-colima-compare-to-lima)
+ - [Are M1 macs supported?](#are-m1-macs-supported)
+ - [Can config file be used instead of cli flags?](#can-config-file-be-used-instead-of-cli-flags)
+ - [Editing the config](#editing-the-config)
+ - [Setting the default config](#setting-the-default-config)
+ - [Specifying the config editor](#specifying-the-config-editor)
+ - [Docker](#docker)
+ - [Can it run alongside Docker for Mac?](#can-it-run-alongside-docker-for-mac)
+ - [Docker socket location](#docker-socket-location)
+ - [v0.3.4 or older](#v034-or-older)
+ - [v0.4.0 or newer](#v040-or-newer)
+ - [Listing Docker contexts](#listing-docker-contexts)
+ - [Changing the active Docker context](#changing-the-active-docker-context)
+ - [Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?](#cannot-connect-to-the-docker-daemon-at-unixvarrundockersock-is-the-docker-daemon-running)
+ - [How to customize Docker config e.g. add insecure registries?](#how-to-customize-docker-config-eg-add-insecure-registries)
+ - [Docker plugins are missing (buildx, scan)](#docker-plugins-are-missing-buildx-scan)
+ - [Installing Buildx](#installing-buildx)
+ - [Installing Docker Scan](#installing-docker-scan)
+ - [How does Colima compare to minikube, Kind, K3d?](#how-does-colima-compare-to-minikube-kind-k3d)
+ - [For Kubernetes](#for-kubernetes)
+ - [For Docker](#for-docker)
+ - [Is another Distro supported?](#is-another-distro-supported)
+ - [Enabling Ubuntu layer](#enabling-ubuntu-layer)
+ - [Accessing the underlying Virtual Machine](#accessing-the-underlying-virtual-machine)
+ - [The Virtual Machine's IP is not reachable](#the-virtual-machines-ip-is-not-reachable)
+ - [Enable reachable IP address](#enable-reachable-ip-address)
+ - [Are Lima overrides supported?](#are-lima-overrides-supported)
+
+## How does Colima compare to Lima?
+
+Colima is basically a higher level usage of Lima and utilises Lima to provide Docker, Containerd and/or Kubernetes.
+
+## Are M1 macs supported?
+
+Colima supports and works on M1 macs but not rigorously tested as the author do not currently possess an M1 device.
+
+Feedbacks would be appreciated.
+
+## Can config file be used instead of cli flags?
+
+Yes, from v0.4.0, Colima support YAML configuration file.
+
+### Editing the config
+
+```
+colima start --edit
+```
+
+For manual edit, the config file is located at `$HOME/.colima/default/colima.yaml`.
+
+For other profiles, `$HOME/.colima//colima.yaml`
+
+### Setting the default config
+
+```
+colima template
+```
+
+For manual edit, the template file is located at `$HOME/.colima/_templates/default.yaml`.
+
+### Specifying the config editor
+
+Set the `$EDITOR` environment variable or use the `--editor` flag.
+
+```sh
+colima start --edit --editor code # one-off config
+colima template --editor code # default config
+```
+
+## Docker
+
+### Can it run alongside Docker for Mac?
+
+Yes, from version v0.3.0 Colima leverages Docker contexts and can thereby run alongside Docker for Mac.
+
+Colima makes itself the default Docker context on startup and should work straight away.
+
+### Docker socket location
+
+#### v0.3.4 or older
+
+Docker socket is located at `$HOME/.colima/docker.sock`
+
+#### v0.4.0 or newer
+
+Docker socket is located at `$HOME/.colima/default/docker.sock`
+
+It can also be retrieved by checking status
+
+```
+colima status
+```
+
+#### Listing Docker contexts
+
+```
+docker context list
+```
+
+#### Changing the active Docker context
+
+```
+docker context use
+```
+### Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
+
+Colima uses Docker contexts to allow co-existence with other Docker servers and sets itself as the default Docker context on startup.
+
+However, some applications are not aware of Docker contexts and may lead to the error.
+
+This can be fixed by any of the following approaches. Ensure the Docker socket path by checking the [socket location](#docker-socket-location).
+
+1. Setting application specific Docker socket path if supported by the application. e.g. JetBrains IDEs.
+
+2. Setting the `DOCKER_HOST` environment variable to point to Colima socket.
+
+ ```sh
+ export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"
+ ```
+3. Linking the Colima socket to the default socket path. **Note** that this may break other Docker servers.
+
+ ```sh
+ sudo ln -sf /var/run/docker.sock $HOME/.colima/default/docker.sock
+ ```
+
+
+### How to customize Docker config e.g. add insecure registries?
+
+* v0.3.4 or lower
+
+ On first startup, Colima generates Docker daemon.json file at `$HOME/.colima/docker/daemon.json`.
+ Modify the daemon.json file accordingly and restart Colima.
+
+* v0.4.0 or newer
+
+ Start Colima with `--edit` flag.
+
+ ```sh
+ colima start --edit
+ ```
+
+ Add the Docker config to the `docker` section.
+
+ ```diff
+ - docker: {}
+ + docker:
+ + insecure-registries:
+ + - myregistry.com:5000
+ + - host.docker.internal:5000
+ ```
+
+### Docker plugins are missing (buildx, scan)
+
+Both buildx and scan can be installed as Docker plugins
+
+#### Installing Buildx
+
+```sh
+ARCH=amd64 # change to 'arm64' for m1
+VERSION=v0.8.2
+curl -LO https://github.com/docker/buildx/releases/download/${VERSION}/buildx-${VERSION}.darwin-${ARCH}
+mkdir -p ~/.docker/cli-plugins
+mv buildx-${VERSION}.darwin-${ARCH} ~/.docker/cli-plugins/docker-buildx
+chmod +x ~/.docker/cli-plugins/docker-buildx
+docker buildx version # verify installation
+```
+#### Installing Docker Scan
+
+Install Synk CLI
+
+```sh
+brew install snyk/tap/snyk
+```
+
+Install Docker Scan
+
+```sh
+ARCH=amd64 # change to 'arm64' for m1
+VERSION=v0.17.0
+curl -LO https://github.com/docker/scan-cli-plugin/releases/download/${VERSION}/docker-scan_darwin_${ARCH}
+mkdir -p ~/.docker/cli-plugins
+mv docker-scan_darwin_${ARCH} ~/.docker/cli-plugins/docker-scan
+chmod +x ~/.docker/cli-plugins/docker-scan
+docker scan --version # verify installation
+```
+
+## How does Colima compare to minikube, Kind, K3d?
+
+### For Kubernetes
+
+Yes, you can create a Kubernetes cluster with minikube (with Docker driver), Kind or K3d instead of enabling Kubernetes
+in Colima.
+
+Those are better options if you need multiple clusters, or do not need Docker and Kubernetes to share the same images and runtime.
+
+Colima with Docker runtime is fully compatible with Minikube (with Docker driver), Kind and K3d.
+
+### For Docker
+
+Minikube with Docker runtime can expose the cluster's Docker with `minikube docker-env`. But there are some caveats.
+
+- Kubernetes is not optional, even if you only need Docker.
+
+- All of minikube's free drivers for macOS fall-short in one of performance, port forwarding or volumes. While port-forwarding and volumes are non-issue for Kubernetes, they can be a deal breaker for Docker-only use.
+
+## Is another Distro supported?
+
+Colima uses a lightweight Alpine image with bundled dependencies.
+Therefore, user interaction with the Virtual Machine is expected to be minimal (if any).
+
+However, Colima optionally provides Ubuntu container as a layer.
+
+### Enabling Ubuntu layer
+
+* CLI
+ ```
+ colima start --layer=true
+ ```
+
+* Config
+ ```diff
+ - layer: false
+ + layer: true
+ ```
+
+### Accessing the underlying Virtual Machine
+
+When the layer is enabled, the underlying Virtual Machine is abstracted and both the `ssh` and `ssh-config` commands routes to the layer.
+
+The underlying Virtual Machine is still accessible by specifying `--layer=false` to the `ssh` and `ssh-config` commands, or by running `colima` in the SSH session.
+
+## The Virtual Machine's IP is not reachable
+
+This is by design. Reachable IP address is not enabled by default because it requires root access.
+
+### Enable reachable IP address
+
+**NOTE:** this is only supported on macOS
+
+* CLI
+ ```
+ colima start --network-address
+ ```
+* Config
+ ```diff
+ network:
+ - address: false
+ + address: true
+
+## Are Lima overrides supported?
+
+Yes, however this should only be done by advanced users.
+
+Overriding the image is not supported as Colima's image includes bundled dependencies that would be missing in the user specified image.
diff --git a/INSTALL.md b/docs/INSTALL.md
similarity index 100%
rename from INSTALL.md
rename to docs/INSTALL.md
diff --git a/environment/container/docker/context.go b/environment/container/docker/context.go
index 4149a1468..3dd3a8809 100644
--- a/environment/container/docker/context.go
+++ b/environment/container/docker/context.go
@@ -9,6 +9,9 @@ import (
// HostSocketFile returns the path to the docker socket on host.
func HostSocketFile() string { return filepath.Join(config.Dir(), "docker.sock") }
+func LegacyDefaultHostSocketFile() string {
+ return filepath.Join(filepath.Dir(config.Dir()), "docker.sock")
+}
func (d dockerRuntime) isContextCreated() bool {
command := fmt.Sprintf(`docker context ls -q | grep "^%s$"`, config.Profile().ID)
diff --git a/environment/container/kubernetes/k3s.go b/environment/container/kubernetes/k3s.go
index 7d3bd383a..6102ba5ce 100644
--- a/environment/container/kubernetes/k3s.go
+++ b/environment/container/kubernetes/k3s.go
@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
- "github.com/abiosoft/colima/environment/vm/lima/network/daemon/vmnet"
-
"github.com/abiosoft/colima/cli"
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/environment"
@@ -123,6 +121,7 @@ func installK3sCluster(
args := []string{
"--write-kubeconfig-mode", "644",
"--resolv-conf", "/etc/resolv.conf",
+ "--flannel-iface", "eth0",
}
if !ingress {
@@ -134,7 +133,6 @@ func installK3sCluster(
if ipAddress != "127.0.0.1" {
args = append(args, "--bind-address", ipAddress)
args = append(args, "--advertise-address", ipAddress)
- args = append(args, "--flannel-iface", vmnet.NetInterface)
}
switch containerRuntime {
diff --git a/environment/vm/lima/cmds.go b/environment/vm/lima/cmds.go
index 9746438bf..58b6bbe1f 100644
--- a/environment/vm/lima/cmds.go
+++ b/environment/vm/lima/cmds.go
@@ -84,7 +84,7 @@ func getIPAddress(profileID, interfaceName string) string {
return strings.TrimSpace(buf.String())
}
-func UbuntuSSHPort(profileID string) (int, error) {
+func ubuntuSSHPort(profileID string) (int, error) {
var buf bytes.Buffer
cmd := cli.Command("limactl", "shell", profileID, "--", "sh", "-c", "echo $"+layerEnvVar)
cmd.Stdout = &buf
@@ -166,17 +166,24 @@ func ShowSSH(profileID string, layer bool, format string) (string, bool, error)
return "", false, fmt.Errorf("error retrieving ssh config: %w", err)
}
+ ip := IPAddress(profileID)
var port int
if layer {
- port, _ = UbuntuSSHPort(profileID)
+ port, _ = ubuntuSSHPort(profileID)
+ // if layer is active and public IP is available, use the fixed port
+ if port > 0 && ip != "127.0.0.1" {
+ port = 23
+ }
+ } else {
+ ip = "127.0.0.1"
}
out := buf.String()
switch format {
case "config":
- out = replaceSSHConfig(out, profileID, port)
+ out = replaceSSHConfig(out, profileID, ip, port)
case "cmd", "args":
- out = replaceSSHCmd(out, profileID, port)
+ out = replaceSSHCmd(out, profileID, ip, port)
default:
return "", false, fmt.Errorf("unsupported format '%v'", format)
}
@@ -184,43 +191,61 @@ func ShowSSH(profileID string, layer bool, format string) (string, bool, error)
return out, port > 0, nil
}
-func replaceSSHCmd(cmd string, name string, port int) string {
+func replaceSSHCmd(cmd string, name string, ip string, port int) string {
var out []string
for _, s := range strings.Fields(cmd) {
- if strings.HasPrefix(s, "ControlPath=") {
- s = "ControlPath=" + strconv.Quote(filepath.Join(config.Dir(), "ssh.sock"))
- }
- if port > 0 && strings.HasPrefix(s, "Port=") {
- s = "Port=" + strconv.Itoa(port)
+ if port > 0 {
+ if strings.HasPrefix(s, "ControlPath=") {
+ s = "ControlPath=" + strconv.Quote(filepath.Join(config.Dir(), "ssh.sock"))
+ }
+ if strings.HasPrefix(s, "Port=") {
+ s = "Port=" + strconv.Itoa(port)
+ }
+ if strings.HasPrefix(s, "Hostname=") {
+ s = "Hostname=" + ip
+ }
}
+
out = append(out, s)
}
if out[len(out)-1] == "lima-"+name {
- out[len(out)-1] = "127.0.0.1"
+ out[len(out)-1] = ip
}
return strings.Join(out, " ")
}
-func replaceSSHConfig(conf string, name string, port int) string {
+func replaceSSHConfig(conf string, name string, ip string, port int) string {
var out bytes.Buffer
scanner := bufio.NewScanner(strings.NewReader(conf))
+
+ hasPrefix := func(line, s string) (pad string, ok bool) {
+ if s != "" && strings.HasPrefix(strings.TrimSpace(line), s) {
+ return line[:strings.Index(line, s[:1])], true
+ }
+ return "", false
+ }
+
for scanner.Scan() {
line := scanner.Text()
- switch {
+ if strings.HasPrefix(line, "Host ") {
+ line = "Host " + name
+ }
- case strings.HasPrefix(strings.TrimSpace(line), "ControlPath "):
- pad := line[:strings.Index(line, "C")]
- line = pad + "ControlPath " + strconv.Quote(filepath.Join(config.Dir(), "ssh.sock"))
+ if port > 0 {
+ if pad, ok := hasPrefix(line, "ControlPath "); ok {
+ line = pad + "ControlPath " + strconv.Quote(filepath.Join(config.Dir(), "ssh.sock"))
+ }
- case strings.HasPrefix(line, "Host "):
- line = "Host " + name
+ if pad, ok := hasPrefix(line, "Hostname "); ok {
+ line = pad + "Hostname " + ip
+ }
- case port > 0 && strings.HasPrefix(line, "Port "):
- pad := line[:strings.Index(line, "P")]
- line = pad + "Port " + strconv.Itoa(port)
+ if pad, ok := hasPrefix(line, "Port"); ok {
+ line = pad + "Port " + strconv.Itoa(port)
+ }
}
_, _ = fmt.Fprintln(&out, line)
diff --git a/environment/vm/lima/network/daemon/gvproxy/gvproxy.go b/environment/vm/lima/network/daemon/gvproxy/gvproxy.go
index bacdc10a4..70da4e762 100644
--- a/environment/vm/lima/network/daemon/gvproxy/gvproxy.go
+++ b/environment/vm/lima/network/daemon/gvproxy/gvproxy.go
@@ -66,7 +66,6 @@ func (*gvproxyProcess) Start(ctx context.Context) error {
}
const (
- NetInterface = "eth1"
SubProcessEnvVar = "COLIMA_GVPROXY"
socketFileName = "gvproxy.sock"
diff --git a/environment/vm/lima/yaml.go b/environment/vm/lima/yaml.go
index f987ac0dd..1a6132b57 100644
--- a/environment/vm/lima/yaml.go
+++ b/environment/vm/lima/yaml.go
@@ -65,16 +65,6 @@ func newConf(ctx context.Context, conf config.Config) (l Config, err error) {
l.Env = make(map[string]string)
}
- // perform mounts in fstab.
- // required for 9p (lima >=v0.10.0)
- // idempotent for sshfs (lima