Skip to content

Cannot overwrite API_BASE_URL on the production docker image #182

@josecelano

Description

@josecelano

The application uses an env var for the API base URL:

API_BASE_URL=http://localhost:3001/v1

For development, you load the value from the .env file. There is a template file for it:

https://github.com/torrust/torrust-index-frontend/blob/develop/dot.env.local#L2

For production, you should be able to change it in two different ways:

Inline runtime configuration (static site)

If you deploy the app like a static site, you must embed the value during the application build. The configuration values are located in the following file:

.output/server/chunks/nitro/node-server.mjs

For example:

const _inlineRuntimeConfig = {
  "app": {
    "baseURL": "/",
    "buildAssetsDir": "/_nuxt/",
    "cdnURL": ""
  },
  "nitro": {
    "envPrefix": "NUXT_",
    "routeRules": {
      "/__nuxt_error": {
        "cache": false
      },
      "/_nuxt/**": {
        "headers": {
          "cache-control": "public, max-age=31536000, immutable"
        }
      }
    }
  },
  "public": {
    "apiBase": "http://localhost:3001/v1"
  }
};

That file is generated when you build the app with npm run build.

Injected runtime configuration (node app)

If you use a node web server, you can inject configuration at runtime. See https://nuxt.com/docs/guide/going-further/runtime-config. Supposedly you can overwrite env var creating env var with the NUXT_ prefix. See https://nuxt.com/docs/guide/going-further/runtime-config#environment-variables.

The current runtime configuration is:

  ssr: false,

  runtimeConfig: {
    public: {
      apiBase: process.env.API_BASE_URL
    }
  },

  modules: [
    "@nuxtjs/tailwindcss"
  ],

  vite: {
    server: {
      fs: {
        // Allow serving files from one level up to the project root
        allow: [".."]
      }
    },
    plugins: [
      eslintPlugin()
    ]
  },

  devtools: {
    enabled: true
  }

});

Issue

The docker image is using a node web server and I trying to change the backend API base URL but it does not change.

If you run a pre-built docker image with:

docker run -it \
    --user="$TORRUST_IDX_FRON_USER_UID" \
    --publish 3000:3000/tcp \
    torrust/index-frontend:3.0.0-alpha.1

The frontend will try to connect to the backend API on the default location:

http://localhost:3001/v1/settings/public

But if I tried to overwrite the value:

docker run -it \
    --user="$TORRUST_IDX_FRON_USER_UID" \
    --publish 3000:3000/tcp \
    --env API_BASE_URL="http://localhost:3010/v1" \
    torrust/index-frontend:3.0.0-alpha.1

The frontend uses the same default value.

You can check the env vars inside the docker container with:

docker run -it \
    --user="$TORRUST_IDX_FRON_USER_UID" \
    --publish 3000:3000/tcp \
    --env API_BASE_URL="http://localhost:3010/v1" \
    torrust/index-frontend:3.0.0-alpha.1 env
USER=appuser
NODE_VERSION=20.2.0
HOSTNAME=90c4f1e00ec2
YARN_VERSION=1.22.19
HOME=/nonexistent
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
API_BASE_URL=http://localhost:3010/v1
UID=1001
RUN_AS_USER=appuser
PWD=/app
TZ=Etc/UTC

Issue cause

While writing this issue I realize you have to overwrite the original en var. This works:

docker run -it \
    --user="$TORRUST_IDX_FRON_USER_UID" \
    --publish 3000:3000/tcp \
    --env NUXT_PUBLIC_API_BASE="http://localhost:3010/v1" \
    torrust/index-frontend:3.0.0-alpha.1

Inside the container, you will have these env vars:

NUXT_PUBLIC_API_BASE=http://localhost:3010/v1
API_BASE_URL=http://localhost:3001/v1

In this case, it works because of the env var name NUXT_PUBLIC_API_BASE. I was using NUXT_API_BASE_URL or API_BASE_URL but Nuxt allows you to override not the ev vars defined in the .env file but the env vars define in the runtimeConfig as javascript object attributes:

For example (from Nuxt docs):

export default defineNuxtConfig({
  runtimeConfig: {
    apiSecret: '', // can be overridden by NUXT_API_SECRET environment variable
    public: {
      apiBase: '', // can be overridden by NUXT_PUBLIC_API_BASE environment variable
    }
  },
})

The env vars should be:

NUXT_API_SECRET=api_secret_token
NUXT_PUBLIC_API_BASE=https://nuxtjs.org

Solution

We are using this env var in the .env file:

API_BASE_URL=http://localhost:3001/v1

And the name does not match the object attribute. We have:

runtimeConfig: {
  public: {
    apiBase: process.env.API_BASE_URL
  }
},

So API_BASE_URL is not the same as NUXT_PUBLIC_API_BASE. And it does not work if you override an env var which is not defined in the runtimeConfig.

I think we added the process.env.API_BASE_URL because we wanted to use a default value when we build the app so that the NUXT_PUBLIC_API_BASE is optional in production.

Nuxt documentation says:

Nuxi CLI has built-in support for reading your .env file in development, build and generate. But when you run your built server, your .env file will not be read.

If that was the reason, we can keep it.

Conclusion

For development, the API base URL is taken from the .env file. When we build the docker image we also inject that value here and it's the default value.

For production, you can use the pre-build docker image or release (if we also start publishing the .ouput artefact) which uses the default value set at building time. If you want, you can overwrite it when you run the new app with the env var NUXT_PUBLIC_API_BASE. It does not work if you are seeing the app as a static app. In that case, you have to build the app by yourself.

I'm going to keep this issue for the record and also to write documentation about it.

cc @da2ce7

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationImproves Instructions, Guides, and Notices

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions