Kubernetes 上的 Node.js 容器中的 Axios 回傳「ECONNREFUSED 127.0.0.1:30561」?

Kubernetes 上的 Node.js 容器中的 Axios 回傳「ECONNREFUSED 127.0.0.1:30561」?

完整錯誤訊息:connect ECONNREFUSED 127.0.0.1:30561 at TCPConnectWrap.afterConnect

axios 請求在 Node.js 環境(Next.js)中運行,這就是錯誤發生的地方,奇怪的是 axios 請求在瀏覽器中運行時運作得很好。

我的元件(在 Node.js 中運行)呼叫 axios:

import axios from 'axios'
import Router from 'next/router'
import React, { Component } from 'react'
import { initializeStore } from '~/reducers'
import { authenticate } from '~/actions/auth'
import { getCookieByName } from '~/helpers/cookie'

const isServer = typeof window === 'undefined'
const __NEXT_REDUX_STORE__ = '__NEXT_REDUX_STORE__'

function getOrCreateStore(initialState) {
    // Always make a new store if server, otherwise state is shared between requests
    if (isServer) {
        return initializeStore(initialState)
    }
    // Create store if unavailable on the client and set it on the window object
    if (!window[__NEXT_REDUX_STORE__]) {
        window[__NEXT_REDUX_STORE__] = initializeStore(initialState)
    }
    return window[__NEXT_REDUX_STORE__]
}

export default App => {
    return class AppWithRedux extends Component {
        static async getInitialProps(appContext) {

            const reduxStore = getOrCreateStore()

            appContext.ctx.reduxStore = reduxStore

            let appProps = {}

            if (typeof App.getInitialProps === 'function') {
                appProps = await App.getInitialProps(appContext)
            }

            const JWT = (isServer ? getCookieByName('JWT', appContext.ctx.req.headers.cookie) : getCookieByName('JWT', document.cookie))

            const pathname = appContext.ctx.pathname

            //set axios baseURL
            axios.defaults.baseURL = (isServer ? `${appContext.ctx.req.headers['x-forwarded-proto']}://${appContext.ctx.req.headers.host}` : window.location.origin)

            //if user has a JWT
            if(JWT){
                axios.defaults.headers.common['Authorization'] = `Bearer ${JWT}`
                //get user from API layer
                reduxStore.dispatch(authenticate())
            } 


            return {
                ...appProps,
                initialReduxState: reduxStore.getState()
            }
        }

        constructor(props) {
            super(props)
            this.reduxStore = getOrCreateStore(props.initialReduxState)
        }

        render() {
            return <App {...this.props} reduxStore={this.reduxStore} />
        }
    }
}

具體來說reduxStore.dispatch(authenticate())

以及我實際的 axios 呼叫(使用 redux thunk),請查看該authenticate方法:

import axios from 'axios'
import { setCookieByName } from '~/helpers/cookie'

const BASE_URL = '/api/auth'
export const TYPE_REGISTER = 'TYPE_REGISTER'
export const TYPE_AUTHENTICATE = 'TYPE_AUTHENTICATE'

export const register = values => (dispatch) => {
    return axios.post(`${BASE_URL}/register`, values)
        .then(function({data: {token, user}}){
            setCookieByName('JWT', token, 365)
            dispatch({
                type: TYPE_REGISTER,
                payload: user
            })
        })
}

export const authenticate = () => (dispatch) => {
    return axios.post(`${BASE_URL}/me`)
        .then(function({data: {user}}){
            dispatch({
                type: TYPE_AUTHENTICATE,
                payload: user
            })
        })
        .catch(function(err){
            console.log(err)
            dispatch({
                type: TYPE_AUTHENTICATE,
                payload: {}
            })
        })
}

我正在使用 Docker for Mac 運行本地 Kubernetes 集群,並且我的 Ingress 控制器正在http://kludge.info:30561.我的網域是從127.0.0.1 kludge.info本地映射的,以允許入口控制器存取容器。我的理論是,例如,當我發送請求時http://kludge.info:30561/api/auth/me,運行 Node.js 應用程式的 docker 容器認為這是對 localhost(容器內部)的請求,並導致連接錯誤。請注意,容器內的 Node.js 應用程式運行在http://localhost:8080.基本上我在我的機器上執行 localhost,並在 Node 實例內執行 localhost。我如何向外部發送請求到http://kludge.info:30561/Ingress 控制器運行的位置。

我也在axios中配置了baseURL,但並沒有解決問題。我的入口控制器有一個/api指向 PHP 實例的路徑,因此我需要 Node.js axios 呼叫來在其容器內呼叫該路徑。任何幫助將非常感激。

當我在 Minikube 上運行 K8 叢集時,沒有遇到這個問題,但是 minikube 確實為您提供了虛擬機器的 IP,而 Docker for Desktop則localhost直接在您的電腦上使用。

相關內容