mrjackwills / oxker

A simple tui to view & control docker containers
MIT License
694 stars 24 forks source link

[BUG] Unable to access docker daemon #30

Closed halostatue closed 1 year ago

halostatue commented 1 year ago

Describe the bug

Oxker will not start.

To Reproduce

  1. oxker
  2. See the screen with the message and auto exit.

Trying to run oxker with no-gui for debugging results in a permanent hang with no messages printed after

2023-07-19T15:35:29.173577Z  INFO oxker: in debug mode

Expected behavior

A screen similar to that which is in the README screenshot. Essentially oxker should be aware of docker contexts, but must be aware of $DOCKER_HOST if set.

Screenshots

CleanShot 2023-07-19 at 11 36 13@2x

Desktop (please complete the following information):

My socket is in ~/.orbstack/run/docker.sock.

Additional context

Setting $DOCKER_HOST does not help.

$ docker context ls
NAME          DESCRIPTION                               DOCKER ENDPOINT                                  ERROR
colima-vz-8   colima [profile=vz-8]                     unix:///Users/austin/.colima/vz-8/docker.sock
default       Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
orbstack *    OrbStack                                  unix:///Users/austin/.orbstack/run/docker.sock
mrjackwills commented 1 year ago

Yeah, oxker should definitely correctly read and handle the $DOCKER_HOST env.

As for the debug mode, again, yes it should force quit(?) if a docker connection cannot be achieved.

In the mean time, I think you should be able to use the DockerHub/ghcr image, but mount your custom socket instead of the default:

docker run --rm -it -v ~/.orbstack/run/docker.sock:/var/run/docker.sock:ro --pull=always mrjackwills/oxker

Although obviously this isn't a good long term solution.

Unfortunately I am away from my computer for at least another week, so I can't test, or implement, any fixes at the moment. Rust 1.71.0 has just been released, and I usually try to follow the same six week release schedule with oxker.

mrjackwills commented 1 year ago

@halostatue I've just pushed a branch fix/host, which I think should solve the issue. A new cli arg is available, --host, to set the docker host path. However, it'll also check for a $DOCKER_HOST env, at the moment the cli arg takes priority over the env - do you think this is the correct order?

Secondly, when in debug mode, it should exit with code 1 if there are any errors - amazed that this hasn't come up before and that I missed this.

If you are unable, or unwilling, to build from source, let me know and I can upload a binary here.

halostatue commented 1 year ago

I’ll need to come back to this in a couple of days, but I can try it from source.

halostatue commented 1 year ago

Sorry for the long delay, but the fix/host branch works when setting $DOCKER_HOST. Ideally, oxker should work such that it can query the Docker contexts to find the current list and get the socket directly:

$ docker context ls --format '{{ . | json }}' | jq -s '.[] | select(.Current == true) | .DockerEndpoint'
"unix:///Users/austin/.orbstack/run/docker.sock"

But this can be considered closed because it now works with $DOCKER_HOST.

mrjackwills commented 1 year ago

@halostatue Thank you for taking the time to check that it works. I wasn't really aware of the Docker context before you submitted the issue. I should probably read the docs further to make sure I fully understand it, to make oxker find the context automatically and correctly as you suggest.

One final note, did you manage to test the --host cli arg, and if so did that work correctly?

Thanks again

halostatue commented 1 year ago

It does:

$ oxker --host (docker context ls --format '{{ . | json }}' | jq -r -s '.[] | select(.Current == true) | .DockerEndpoint')

(I use fish, so that’s why the lack of $.)

mrjackwills commented 1 year ago

Perfect thanks, I'll merge the branch, and probably wait til rust 1.72.0 on August 24th before publishing a new version. Will do some testing about auto context finding that can be terminal agnostic.

halostatue commented 1 year ago

I’ve done a bit more research, and I think that there’s an opportunity for a crate here to improve Docker context support across Rust projects. I suspect that there’s explicit code that could be translated from Go in the docker command-line itself, but here’s what I have seen:

meta.json:

{
  "Name": "orbstack",
  "Metadata": {
    "Description": "OrbStack"
  },
  "Endpoints": {
    "docker": {
      "Host": "unix:///Users/austin/.orbstack/run/docker.sock",
      "SkipTLSVerify": false
    }
  }
}

docker context inspect --format json orbstack

[
  {
    "Name": "orbstack",
    "Metadata": {
      "Description": "OrbStack"
    },
    "Endpoints": {
      "docker": {
        "Host": "unix:///Users/austin/.orbstack/run/docker.sock",
        "SkipTLSVerify": false
      }
    },
    "TLSMaterial": {},
    "Storage": {
      "MetadataPath": "/Users/austin/.docker/contexts/meta/2d89b732b01a00a2d1675ed3cee9fd0f965daadf90603c989dd3afd4569c6896",
      "TLSPath": "/Users/austin/.docker/contexts/tls/2d89b732b01a00a2d1675ed3cee9fd0f965daadf90603c989dd3afd4569c6896"
    }
  }
]

Ignoring the fact that docker context inspect --format json returns an array, there are two additional keys TLSMaterial (unknown contents, empty in my context) and Storage (which is constructed from the discovered file paths themselves).

I’m not good enough with Rust to build such a crate, nor do I really have an interest in maintaining such a crate (my interest in Docker and related tools is as a user, not someone who wants to build tools for Docker), but this is what I have found.

mrjackwills commented 1 year ago

Thank you, highly informative and helpful.

oxker uses a crate called bollard to communicate with Docker. They actually have an open issue at the moment that I think might be related (I still haven't read enough into the Docker context, it's on my todo list) https://github.com/fussybeaver/bollard/issues/310

halostatue commented 1 year ago

The issue isn’t related to contexts, but is related to automatic resolution of $DOCKER_HOST if it isn’t pointing to a Unix socket, if I’m reading it correctly. That said, bollard is probably the right place to add this functionality, since it’s where connections are resolved.

If I were to weigh in on that, I would suggest:

Those could also be simplified as Docker::connect_with_defaults() or Docker::connect(), but I’m not sure that the creator of bollard would want that, based on the comments there.

If you decide to implement this independently of bollard, you would basically be getting the EndPoints.docker.Host value and using Docker::connect_with_socket() if it does not start with tcp:// and Docker::connect_with_ssl() if it starts with tcp:// and SkipTLSVerify is false (the default).