1

I can make cUrl calls to Docker API but if I run the same script from a container (docker-compose), I can't reach any API endpoint.

My requests looks like :

$ curl --unix-socket /var/run/docker.sock -X POST http:/localhost/containers/json

The reason could be the use of localhost but I can't find the solution for now. Any suggestions?

EDIT : Here's a brief summary of the stack i'm using (Api-Platform https://api-platform.com/). Every container is attached to an "api_default" bridge network :

  • php = Symfony based application
  • nginx = NGINX web server
  • psql = Hosts the main database
  • mssql = Used to sync datas
  • ...

I do have a shell script in my "php" container which is meant to reach the Docker API. To summarize, I request the "mssql" container to sync with an external service and then I ask to "psql" container to copy those datas (export/import done with csv files through shared volumes).

The problem is :

  • If I do docker-compose exec php bin/console app:sync (Symfony command which runs the script), everything works fine : the containers communicate through docker.sock with the Docker API and I can sync my databases.
  • But if I run the same script with an api endpoint (localhost:8080/api/sync) or via a VueJS app (Axios), the Docker API never return any response.

Below is a part of my script :

curl -XPOST -H 'Content-Type: application/json' \
      --unix-socket /var/run/docker.sock http:/localhost/containers/mssql/exec \
      -d '{
        "AttachStdout":true,
        "Tty":true,
        "Cmd":["/opt/mssql-tools/bin/sqlcmd", ...]
      }'

And here is the way I call my Symfony command in the api endpoint Controller :

 /**
  * @Route("/api/sync", name="sync", methods={"GET"})
  */
  public function sync(KernelInterface $kernel)
  {
    $application = new Application($kernel);
    $application->setAutoExit(false);

    $input = new ArrayInput(array(
        'command' => 'app:sync'
    ));

    $output = new BufferedOutput();
    $application->run($input, $output);
    $content = $output->fetch();

    return new Response($content);
  }

Maybe should I replace "localhost" with "api_default" to reach the good network, but that doesn't work ... ?

Veverke
  • 9,208
  • 4
  • 51
  • 95

2 Answers2

1

the localhost you try to connnect is the localhost in the container you run curl

you should find and replace with its host ip

BMW
  • 42,880
  • 12
  • 99
  • 116
1

Yep. If you want to communicate between one docker container and another docker container, at the very least, you need to use the service name instead of localhost because, as @BMW said, localhost is relative to the machine you are on, and from the container's point of view, localhost is the container itself.

I had a similar situation recently where it wasn't enough to use the service name. I also had to create a network and add each service to that network. Like this:

my_service:
    ...
    ...
    ...
    networks:
      - backend

networks:
  backend:
    driver: bridge
Eric McLachlan
  • 3,132
  • 2
  • 25
  • 37
  • Hi, there's already a bridge network in my stack named "api_default". How could I reach it ? `curl http:/api_default/containers/json` ? Already tried but no more luck ... – user12934448 Feb 24 '20 at 12:15
  • I think that, instead of using the network name in the URI, use the service name. So, http://my_service/containers/json... If you're struggling to find an answer (like I was a while ago), you can use `docker exec -it container_name sh` to open a shell on the container. Then you can try and curl from within the container to see what works. – Eric McLachlan Feb 24 '20 at 13:06