【问题标题】:CURL not working in Docker Image [Unable to access the host in Docker image]CURL 在 Docker 映像中不起作用 [无法访问 Docker 映像中的主机]
【发布时间】:2020-06-03 08:27:05
【问题描述】:

Docker 文件

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

# Add Maintainer Info
LABEL maintainer="Sumit Thakur <sumitthakur@yahoo.com>"

# 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"]

使用构建 Docker 文件

docker build -t testapp  -f Dockerfile .

这是完美的工作

运行 Docker 文件

docker run -d -p 50051:50051 testapp

这样也能正常工作

我检查正在运行的容器

docker ps

这会给我

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

当我检查网络检查时

docker network inspect bridge

这会给我

[
    {
        "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": {}
    }
]

一切正常 除非我尝试连接 docker 主机

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'

它给了我

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

测试openssl:

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

结果:

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)
---

申请代码

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!")
}

任何人帮助我被困在这里 1-2 天不知道该怎么办?

【问题讨论】:

  • 你能在容器内卷曲端点吗?
  • 是的,如果我执行docker exec -it &lt;name&gt; bash 并执行./testapp 然后我点击 curl 它会给我结果
  • 我不明白为什么我无法从系统卷曲。我只是卡在那里。
  • 请使用curl -H "Content-type:application/json" -X GET 'http://localhost:50051/testapp/v1/order' -v 并发布输出。查看日志服务器端。可能你打的是http而不是https
  • 谢谢,它现在会显示我curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to localhost:50051

标签: docker go curl docker-compose handshake


【解决方案1】:

从评论中的讨论来看,问题似乎与https 握手有关。

一个简单的解决方案是使用以下 URL 查询服务:

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

使用-k,您将忽略HTTPS 验证。

注意:我已将 URL 从 http 更改为 https

【讨论】:

  • 它现在会给我curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to localhost:50051
  • 您确定您使用的是https 网站而不是http?在这种情况下,请运行这些命令并发布输出:openssl s_client https://localhost:50051/testapp/v1/order-connectgnutls-cli https://localhost:50051/testapp/v1/order
  • 我在上面更新了 openssl s_client 的输入/输出。请检查
【解决方案2】:

从容器内部,您需要监听所有接口,而不是 localhost 或环回接口。网络是在 docker 中命名的,因此您不仅可以获得一个新的私有 ip,还可以获得容器内部一个无法从外部访问的单独环回接口。为此,请更改:

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

收件人:

http.ListenAndServe(":50051", headersOk)

【讨论】:

  • 是的,我改变了我会在上面更新,但是当我点击 curl 时它会给我curl: (35) error:1400410B:SSL routines:CONNECT_CR_SRVR_HELLO:wrong version number
  • @SumitBon 这里没有配置 SSL,从你的问题返回你原来的 curl 命令,http,而不是 https。
  • 我这样做了,但如果我在 docker 容器 中运行 curl,我会遇到问题,但它工作正常,但从 system我的结果curl: (7) Failed to connect to 0.0.0.0 port 50051: Connection refused 不明白为什么会发生这种情况
  • @SumitBon 你原来的命令没有卷曲到0.0.0.0,它是localhost,使用原来的卷曲命令。
【解决方案3】:
  1. main.go 上提供的代码不会启动 TLS,所以停止使用https 进行 curl,它不会起作用。 curl 与 http 将起作用

    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. openssl s_client https://localhost:50051/testapp/v1/order -connect localhost:50051 命令向您确认您请求的端口上不存在 TLS

  3. 很多 cmets 确认使用 https 不相关,再次在您的代码上未激活 TLS

  4. curl -H "Content-type:application/json" -X GET 'http://localhost:50051/testapp/v1/order' 有效。 再次确认没有使用TLS

结论:

当您的代码上未激活 TLS 时,不要尝试 curl https

【讨论】:

  • 谢谢我完全理解你的意思,但这是我的问题,一切都很完美,除非我在容器内运行 curl 它工作正常,但从系统它给了我结果curl: (7) Failed to connect to 0.0.0.0 port 50051: Connection refused
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 2021-10-09
  • 2017-01-06
  • 2018-06-06
  • 1970-01-01
  • 1970-01-01
  • 2017-09-07
相关资源
最近更新 更多