无法通过 Docker 连接到 Cloud SQL 代理 - 错误:连接 ENOENT

问题描述 投票:0回答:4

我似乎无法使用 Docker 容器连接到 CloudSQL。

首先这是我的文件路径:https://i.sstatic.net/iddC9.jpg

Dockerfile.dev:


FROM node:14-slim

WORKDIR /usr/src/app


COPY package*.json ./


RUN npm install


COPY . ./

Dockerfile.sql

RUN mkdir /cloudsql
WORKDIR /usr/src/app


COPY package*.json ./

RUN npm install


COPY ./cloud_sql_proxy ./
COPY ./service_acct.json ./

version: '3.8'
services: 
    cloud-sql-proxy:
        build: 
            context: .
            dockerfile: DockerFile.sql
        volumes: 
            - /cloudsql:/cloudsql
            - /service_acct.json:/app/service_acct.json
        command: ./cloud_sql_proxy -dir=/cloudsql -instances=test-game-199281:us-east1:testgame -credential_file=/app/service_acct.json
      
    app:
        build: 
            context: .
            dockerfile: DockerFile.dev
        env_file: 
            - ./.env
        volumes: 
            # since we copied root into host in dockerfile, we can map the whole directory with app.
             - "./src:/app/src"
        
        ports: 
            - "5000:5001"
        command: sh -c "npm run dev"

我的节点index.js 文件。我不认为有什么问题,也许我输入了错误的连接字符串格式?据我所知,密码和用户是正确的。

const express = require('express');
const { Pool, Client } = require('pg')
const app = express();
require('dotenv').config({path:'../.env'})

const pool = new Pool({
    user: 'postgres',
    host: '/cloudsql/test-game-199281:us-east1:testgame',

    database: 'TestDB',
    password: '********',
    port: 5432
    
  })

  
app.get('/', (req, res) => {
    pool.connect(function(err, client, done) {
        if (err) {
            console.log("not able to get connection " + err);
            res.status(400).send(err);
            return
        }
        client.query("SELECT * FROM company", [1], (err, result) =>{
            done();
            if (err) {
                console.log(err);
                res.status(400).send(err);
            }
            res.status(200).send(result.rows);
        });
    });

});

我得到的错误:

Hello world listening on port 5001

app_1 | Error: connect ENOENT /cloudsql/test-game-199281:us-east1:testgame

/.s.PGSQL.5432

app_1 | at PipeConnectWrap.afterConnect [as oncomplete] (net.js:1146:16) {

app_1 | errno: -2,

app_1 | code: 'ENOENT',

app_1 | syscall: 'connect',

app_1 | address: '/cloudsql/test-game-199281:us-east1:testgame

/.s.PGSQL.5432'

app_1 | }

已解决:我切换到 TCP。螺丝unix插座。太混乱了。

node.js docker google-cloud-platform google-cloud-sql
4个回答
2
投票

您已指示 Cloud SQL Auth 代理使用此标志

0.0.0.0:5432
监听
-instances=test-game-199281:us-east1:testgame=tcp:0.0.0.0:5432

但是你已经指示你的应用程序连接到

/cloudsql/<INSTANCE_CONNCECTION_NAME>
,这是一个 unix 套接字。

您需要选择一个,并确保您的应用程序和代理之间保持一致。

如果您使用 TCP,您必须将容器中的端口映射到您计算机上的端口(或者您的应用程序可以访问的 docker-compose 网络中的某个位置)。您必须更新您的应用程序才能连接上

127.0.0.1
(或者其 docker IP 在网络中的任何位置)。您可以在here查看有关 docker-compose 网络的更多信息。

如果您使用 Unix 域套接字,则需要批量共享包含该套接字的文件夹,以便两个应用程序都可以访问它。因此,如果它位于

/cloudsql
中,您需要在代理容器和应用程序容器之间共享
/cloudsql
。您可以在here查看有关 docker-composevolumes 的更多信息。

Cloud SQL 的管理数据库连接页面 有使用 TCP 和 Unix 域套接字连接的示例


0
投票

不同docker之间连接时,可以尝试通过服务名

cloud-sql-proxy:5432
来连接,而不是
localhost:5432

每个 docker 都是一个独立的网络,因此您不能使用 localhost,因为 localhost 将引用 docker 容器自己的本地网络。


0
投票

ENOENT
错误意味着连接器实用程序无法找到连接到数据库的主机。这是一个很好的答案,进一步解释了它。

在您的 docker-compose 文件上,Cloud SQL 代理正在通过 TCP 进行侦听,但您的代码正在尝试通过 Unix 套接字进行连接。您的代码无法连接到主机,因为套接字不存在。

解决方案是配置代理以创建并监听 Unix 套接字。将命令更改为:

/cloud_sql_proxy -instances=INSTANCE_CONNECTION_NAME -dir=/cloudsql -credential_file=/tmp/keys/keyfile.json

无需公开任何端口即可通过 Unix 套接字进行连接。我还建议使用上面链接中的配置对象或按

pg-pool
指定的配置对象构建池连接,而不是使用数据库 URL,以避免可能出现的问题,即无法使用
connectionString
连接到 Unix 套接字网址。


0
投票

对于你原来的问题 - 根据另一个线程的答案,Unix Socket 方法似乎根本不可能:https://stackoverflow.com/a/77588828/2809427

你永远无法在容器和主机之间共享 Unix 套接字 [...] 如果两个进程不使用相同的内核,它们将无法共享 Unix 套接字。

© www.soinside.com 2019 - 2024. All rights reserved.