cli icon indicating copy to clipboard operation
cli copied to clipboard

--add-host example doesn't work as shown

Open kodedylf opened this issue 1 year ago • 7 comments

In the documentation at https://github.com/docker/cli/blob/master/docs/reference/commandline/container_run.md#add-host, a python3 web server is run to server the hello file.

However, as shown, the command will run in the foreground and the user will be unable to run the rest of the commands in the same terminal session. If the user presses ctrl-c to terminate python to be able to run the container, the example won't work since the web server isn't running.

My own solution was to run python3 in the background by adding & to the command. However then I needed to kill the web server after running the container. Getting the pid and killing python isn't very elegant. Hopefully you can come up with a better solution.

kodedylf avatar Oct 20 '24 17:10 kodedylf

Thanks for reporting!

Hm... yes, that's a good one; I know we tried to write up a minimal-as-possible example just to illustrate the concept, but indeed running things in the background can be slightly tricky, or at least to keep things "simple" as well as (where possible) working across platforms (mac, linux, windows).

I guess a "scrappy" workaround here could be to have the user open two separate shells; one to run the Python server and another one to run the docker commands to connect to it.

@neersighted @dvdksn any thoughts / ideas ?

thaJeztah avatar Oct 20 '24 19:10 thaJeztah

@thaJeztah How about using Docker Compose?

  1. Create a Dockerfile for the Python Server
# Use the official Python image
FROM python:3.9-slim

WORKDIR /usr/src/app

# Copy the hello file into the image
COPY hello.txt .

# Start the HTTP server
CMD ["python3", "-m", "http.server", "8000"]
  1. Now create a file named docker-compose.yml
version: '3.8'

services:
  python-server:
    build:
      context: .
    ports:
      - "8000:8000"

  curl-client:
    image: curlimages/curl
    depends_on:
      - python-server
    entrypoint: ["curl", "-s", "host.docker.internal:8000/hello"]
    extra_hosts:
      - "host.docker.internal:host-gateway"
  1. Build and Run the Containers
docker-compose up --build

ghost avatar Nov 01 '24 13:11 ghost

Right, but the host.docker.internal feature was added for users to have an option to connect to a services that's not running inside a container, so some service on the host. For the docker-compose case, the recommended approach would for the curl-client service to connect with the python-server service through the internal network (are least; "don't map ports that shouldn't be accessible publicly").

thaJeztah avatar Nov 01 '24 13:11 thaJeztah

I guess we could use nc to send a response (and terminate itself after); also means we don't need python (which may not be installed?). It may be a bit obscure though 🤔

printf 'HTTP/1.1 200 OK\r\n\r\nhello from host!\n' | nc -l 8000 & disown

docker run -q --rm \
  --add-host host.docker.internal=host-gateway \
  curlimages/curl -s host.docker.internal:8000
GET / HTTP/1.1
Host: host.docker.internal:8000
User-Agent: curl/8.13.0
Accept: */*

hello from host!

thaJeztah avatar Apr 25 '25 00:04 thaJeztah

@thaJeztah I like it

dvdksn avatar Apr 25 '25 09:04 dvdksn

Yeah, that's where my thinking for nc came from here; it should only produce a response once, then terminate, so as long as the reader followed the example and made the connection, it would be gone afterwards.

thaJeztah avatar Apr 25 '25 18:04 thaJeztah

I need to add a -q 0 option on nc to get it to close the connection after sending the text. I'm on Ubuntu and I think it's the OpenBSD version of nc. I found this which indicates that different versions of nc need different options to get them to close the connection.

When I ran it without -q 0, curl hangs while waiting for the connection to get closed. And nc didn't terminate.

But with the -q 0 option it works well for me.

Edit: There's an -N option on nc that works too.

kodedylf avatar Apr 25 '25 18:04 kodedylf