Environment variable NODE_ENV being ignored?

So I am trying to deploy an Node.js + express web app to Fly.io. The website works correctly, but I just realized it never detects the NODE_ENV variable, even if I added it to the fly.toml file:

This is the output after running $ flyctl deploy

[Installing Node.js distribution]
Reusing Node.js 18.9.1
[INFO] Installing toolbox
[INFO] Using npm v8.19.1 from Node
[INFO] Reusing node modules

[Warning: Skip pruning because NODE_ENV is not 'production'.]

And you can see how in the file it is set:

$ cat fly.toml 
# fly.toml file generated for myaccount on 2022-09-25T18:29:52+02:00

app = "myaccount-app"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []

  builder = "heroku/buildpacks:20"

  NODE_ENV = "production"
  PORT = "8080"

# Some other stuff here

Could anyone tell me what am I doing wrong?

Try checking what flyctl logs is responding back with and also check Fly.io Docs: env you might need to place some sensitive information with Fly.io Docs: secrets which should allow your app to detect what’s missing.

There’s nothing in the logs, and I have some other env variables set in fly.toml that are correctly set within my app.

Secrets and env vars aren’t automatically injected into the Docker builder during deployment (I know, that’s a “fun” fact), so you need to use some combination of the following to get those into the Docker builder.

fly deploy \
    --build-args="foo=bar" \
    --build-secrets="bar=baz" \
    -e "foo=bar"

Secrets in particular require a bit of extra work to use in your Dockerfile : Build Secrets · Fly Docs

1 Like

Fly’s more strict with secrets (a good thing!), but if folks could set secrets for remote builders, then that should work-out nicely afa devex is concerned?

That is, imagine if fly secrets set k1=v1 k2=v2 -a <free-builder-name> set approp env vars for remote deploys?

fly env set k1=v1 k2=v2 -a <free-builder-name> would also be neat.

Thanks for the info! I am not an expert with deploying websites and DevOps in general. In this case then, the problem is that the docker builder is not detecting this variable, so I should inject it in the deployment with the call:
flyctl deploy --build-args="NODE_ENV=production"
Is this correct?

Yes, mostly!

I’m not exactly sure how the buildpack operates (vs using a Dockerfile), I would experiment with:

fly deploy -e "NODE_ENV=production"

The --build-args flag likely requires a Dockerfile with an ARG defined in it.

I see… I have tried with:

flyctl deploy -e "NODE_ENV=production"
flyctl deploy -e NODE_ENV="production"
flyctl deploy -e NODE_ENV=production

So finally I tried with:

flyctl deploy --build-arg NODE_ENV=production

And it did work (I think), I see some other warnings now, like:

[INFO] Installing node modules from ./package-lock.json
npm WARN config production Use `--omit=dev` instead.

But it looks like now it is pruning the dev dependencies, so I expect NODE_ENV to be production.

[INFO] Successfully pruned devdependencies!

Thank you.

EDIT: Also, a [build.args] section can be added to the fly.toml file to not have to add the variable every time manually.

1 Like

Another way is, to set it with the ENV directive of the Dockerfile.