docker.net-coredocker-compose

Posting API request from one Docker container to another


I've been following this post on Medium to learn how to create and run a dotnet core console app in a docker container, and post to a dotnet core API in another container.

When I run the two applications side-by-side (without docker, i.e. just debugging in vscode), everything works OK - the console app can post to the API. However, when I run the applications in containers using docker-compose up --build, I get an error when the application tries to post to the api:

Unhandled exception. System.AggregateException: One or more errors occurred. (The SSL connection could not be established, see inner exception.)

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.

System.IO.IOException: The handshake failed due to an unexpected packet format.

Searching for solutions to this error hasn't helped much, and I feel that the problem may simply be connectivity between the two containers, but I've had no luck trying to resolve it.

My docker-compose file is as follows:

version: '3.4'

services:
  publisher_api: 
    image: my_publisher_api:latest
    container_name: my_publisher_api_container
    build: 
      context: ./publisher_api
      dockerfile: Dockerfile

  worker:
    image: my_worker
    container_name: my_worker_container
    depends_on: 
      - "publisher_api"
    build:
      context: ./worker
      dockerfile: Dockerfile

My console app code (or at least the relevant part) is:

public static async Task PostMessage(object postData)
{
    var json = JsonConvert.SerializeObject(postData);
    var content = new StringContent(json, UnicodeEncoding.UTF8, "application/json");

    using (var httpClientHandler = new HttpClientHandler())
    {
        httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
        using (var client = new HttpClient(httpClientHandler))
        {
            var result = await client.PostAsync("https://my_publisher_api_container:80/values", content);
            string resultContent = await result.Content.ReadAsStringAsync();
            Console.WriteLine($"Server returned {resultContent}");
        }
    }
}

I wont post any of the API code, as I dont think any of it should be relevant, but please let me know if you think it would help.

If anyone has any idea on what the cause of this error is or how to resolve it, I'd appreciate the help.

Edit

Thought it would be useful to include the versions being used:


Solution

  • Looks like I had mad a couple of fairly obvious mistakes, however they're not so obvious when you're completely new to Docker, like me.

    1. The hostname to post to should be the name of the service, not the container.In my case, I had to change the console app to post to the name of the API service declared in the docker-compose file, publisher_api.

    2. Use HTTP instead of HTTPS. When I debugged the API locally, it launches with HTTPS by default. I assumed I would use HTTPS when running the container in docker, but this doesn't seem to work by default. Changing to HTTP resolved the issue (although this ideally will be a short-term solution).

    So just for completeness, here's my updated code. Only the URL that the console app posts to had to change:

    public static async Task PostMessage(object postData)
    {
        var json = JsonConvert.SerializeObject(postData);
        var content = new StringContent(json, UnicodeEncoding.UTF8, "application/json");
    
        using (var httpClientHandler = new HttpClientHandler())
        {
            httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
            using (var client = new HttpClient(httpClientHandler))
            {
                var result = await client.PostAsync("http://publisher_api80/values", content);
                string resultContent = await result.Content.ReadAsStringAsync();
                Console.WriteLine($"Server returned {resultContent}");
            }
        }
    }