Sumit Bon
Sumit Bon

Reputation: 49

CURL not working in Docker Image [Unable to access the host in Docker image]

Docker File

# Start from the latest golang base image
FROM golang:latest

# Add Maintainer Info
LABEL maintainer="Sumit Thakur <[email protected]>"

# Set the Current Working Directory inside the container
WORKDIR /app

# Copy go mod and sum files
COPY go.mod go.sum ./

# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed
RUN go mod download

# Copy the source from the current directory to the Working Directory inside the container
COPY . .

# Build the Go app
RUN go build -o testapp myapplication.go testapp.go

# Expose port 50051 / for internal comunication 

ENV PORT 50051
RUN echo $PORT

EXPOSE ${PORT}

# Command to run the executable
CMD ["./testapp"]

Build Docker file with

docker build -t testapp  -f Dockerfile .

that's perfect working

Run Docker file

docker run -d -p 50051:50051 testapp

that's will also working fine

I check with the running container

docker ps

this will give me

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                      NAMES
57cd3c01bcda        testapp           "./testapp"       2 seconds ago       Up 2 seconds        0.0.0.0:50051->50051/tcp   gracious_bhaskara

and when i check the network inspect with

docker network inspect bridge

this will give me

[
    {
        "Name": "bridge",
        "Id": "30850a823d3040e7d8eaf804c122ce3d26b35650f6f792cf1f4ce77d66167eeb",
        "Created": "2020-02-19T07:34:24.993299775Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "57cd3c01bcda3fbf7d0bf67136ebbb8afb312c4f6ca70eeee15cda6e10fff4e2": {
                "Name": "gracious_bhaskara",
                "EndpointID": "2a42056609e8140d190f1efde41320138867d3905053e7f381bd91b1f053c251",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

Everthing works fine Except when i trying to connect the docker host

curl -H "Content-type:application/json" -X GET 'https://localhost:50051/testapp/v1/order'
or
curl -H "Content-type:application/json" -X GET 'https://172.17.0.2:50051/testapp/v1/order'

it gives me

Note: Unnecessary use of -X or --request, GET is already inferred.
*   Trying 0.0.0.0...
* TCP_NODELAY set
* Connected to 0.0.0.0 (127.0.0.1) port 50051 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* error:1400410B:SSL routines:CONNECT_CR_SRVR_HELLO:wrong version number
* stopped the pause stream!
* Closing connection 0
curl: (35) error:1400410B:SSL routines:CONNECT_CR_SRVR_HELLO:wrong version number

Test openssl:

openssl s_client https://localhost:50051/testapp/v1/order -connect localhost:50051 

Result:

CONNECTED(00000005)
4488771180:error:140040E5:SSL routines:CONNECT_CR_SRVR_HELLO:ssl handshake failure:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.200.4/l
ibressl-2.6/ssl/ssl_pkt.c:585:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 
    Start Time: 1582109828
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

Application Code

package main

import (
    "io"
    "net/http"
    "github.com/gorilla/handlers"
)
func main() {
    http.HandleFunc("/testapp/v1/order", testHandler)
    headersOk := handlers.AllowedHeaders([]string{""})
    http.ListenAndServe(":50051", headersOk)
}
func testHandler(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "Heyyy!")
}

Anyone Help I'm stuck here 1-2 days don't know what to do ?

Upvotes: 4

Views: 12468

Answers (3)

J-Jacques M
J-Jacques M

Reputation: 1118

  1. The code provided on main.go does not start TLS, so stop tring to curl with https, it won't works. curl with http will work

    package main
    
    import (
        "io"
        "net/http"
    
        "github.com/gorilla/handlers"
    )
    
    func main() {
        http.HandleFunc("/testapp/v1/order", testHandler)
        headersOk := handlers.AllowedHeaders([]string{""})
        http.ListenAndServe(":50051", headersOk)
    }
    func testHandler(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Heyyy!")
    }
    
  2. The command openssl s_client https://localhost:50051/testapp/v1/order -connect localhost:50051 confirm to you that TLS is not present on the port you requested

  3. Lot of comments confirm that using https is not relevant, again TLS is not activated on your code

  4. curl -H "Content-type:application/json" -X GET 'http://localhost:50051/testapp/v1/order' works. That confirm again TLS is not used

Conclusion:

Do not try to curl https when TLS is not activated on your code

Upvotes: 0

BMitch
BMitch

Reputation: 263469

From inside the container, you need to listen on all interfaces, not localhost or the loopback interface. Networking is namespaced in docker, so you get not only a new private ip, but also a separate loopback interface inside the container that cannot be reached externally. To do this, change:

http.ListenAndServe("localhost:50051", headersOk)

To:

http.ListenAndServe(":50051", headersOk)

Upvotes: 0

alessiosavi
alessiosavi

Reputation: 3037

From the discussion in the comment, the problem seems related to the https handshake.

A simple solution, is to query the service using the following URL:

curl -H "Content-type:application/json" -X GET 'https://localhost:50051/testapp/v1/order' -v -k

Using the -k, you are going to ignore the HTTPS validation.

NOTE: i've changed the URL from http to https.

Upvotes: 1

Related Questions