I want to deploy my Node.js application in Pivotal Cloud Foundry using manifest.yml. I need to update the PATH variable of the container before the application starts, to include the path of a directory in my application's src directory. Can this be achieved?
manifest.yml:
---
applications:
- name: node-apollo-graphql-server
command: npm start
instances: 1
memory: 512M
buildpack: dicf_nodejs_buildpack_rc
stack: cflinuxfs3
You cannot do this by setting env variables with cf push -e or the env: block in manifest.yml. If you set path using one of these methods, you'll override path when what you likely want to do is append to it.
To append to $PATH, add a file .profile to the root of your project (directory from which you're running cf push). In that file, put one line export PATH=$PATH:<new loc> where <new loc> is the path you want to append to the $PATH env variable.
The .profile file is sourced before your application starts so you can use this to dynamically set environment variables or apply configuration before your application starts up.
The only caveat is that this happens before your application starts so it blocks the starting of your application. As such, you should avoid running expensive/time-consuming processes here. Otherwise, you will delay the start of your application, or possibly even cause app failures if you exceed the startup timeout (cf push -t).
Related
I have a basic "service unit" file like the following.
[Unit]
Description=Certprovider service
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=5s
ExecStart=/home/mert/certprovider/certprovider
WorkingDirectory=/home/mert
User=root
Group=root
[Install]
WantedBy=multi-user.target
I have the .env file in the root of the project.
CA_DIR_URL=https://acme-v02.api.letsencrypt.org/directory
EMAIL=mertsmsk0#gmail.com
HOST=127.0.0.1
PORT=8557
I load this file with the following lines.
err := godotenv.Load()
if err != nil {
log.Fatalln("Error loading .env file")
}
Service has been working very well but I cannot reach the PORT environment variable. Thus I cannot start the webserver because that port cannot listen. I print all the environment variables that in the .env excluding PORT. I changed its name to APP_PORT but it same thing.
The mystery part is I can reach other variables in the .env file. In addition to that when I add the following line in the unit file, I can reach that variable but I don't understand that why should I add only the PORT variable in the unit file?
[Service]
Environment=PORT=8557
It's happening when I try to run it as a binary file. Because I can reach the variables with the following command.
go run .
If you call Load without any args it will default to loading env in the current path.
Your current path is configured here:
WorkingDirectory=/home/mert
And yet, you say (emphasis added)
I have the .env file in the root of the project.
But that's not the current working directory.
root of the project
That concept is not meaningful to the application runtime. Unlike interpreted languages like, say, PHP, Go compiles to a static binary that is functionally entirely distinct from the set of libraries and sources that define it. In PHP (or python, ruby, etc) those libraries have no other place to be, than the root of some project directory.
In go, that stuff is only relevant for development and testing. The fact that your executable appears to be in your "root of the project" is entirely incidental and completely meaningless.
If you really want to put the runtime configuration in tht particular file, in that particular place, just set that as the working directory:
ExecStart=/home/mert/certprovider/certprovider
WorkingDirectory=/home/mert/certprovider/certprovider
I would put that stuff in /usr/local so I didn't accidentally break my let's encrypt while fiddling with stuff in my home directory - doubly so for let's encrypt because it might take up to 90 days to realize your certs weren't being refreshed. I'd put the config outside of my home directory for the same reason.
Actually, for this case I'd probably put all the config in the unit file. Why not put it there? But of course, that's a matter of opinion. If you really want to use the automatic .env discovery then you should dedicate a directory to containing that hidden file. It doesn't make much sense to put a config specific to one application in ~/.env.
Wherever you put .env, make sure that's your working directory so it will be discovered.
I print all the environment variables that in the .env excluding PORT. I changed its name to APP_PORT but it same thing. [...]
The mystery part is I can reach other variables in the .env file.
Respectfully, that sounds like an assumption on your part. Without evidence to the contrary, it's easy to conclude that you have set defaults for these values or that they're coming from some other source or behavior. That's more parsimonious than concluding the godotenv library read some, but not all, the values from a file.
It's happening when I try to run it as a binary file. Because I can reach the variables with the following command. [go run .]
Go always runs as a binary. go run . simply automatically builds the binary in a temp location and then runs it. Why is it recommended to use `go build` instead of `go run` when running a Go app in production? talks about why go run is often contraindicated on SO.
this should have been routine, but I haven't been able to find any way. I am using Node with Docker for packaging. I have three environments: dev, qa, and prod, as usual. I have three configuration files with numerous variables: dev-config.json, qa-config.json, prod-config.json. I need Docker to pick up files and package them as config.json inside the Docker image. How to go about pl.. Thx
For building an image with only the correct config file included, you can use --build-arg.
Add
ARG CONFIG_FILE
...
COPY $CONFIG_FILE config.json
in your docker file and then use
docker build --build-arg CONFIG_FILE=prod-config.json .
to build your image
EDIT
The other possibility is to put all your config files in your image and decide which one to use, when you startup the container. For instance, you could read the desired name of your config file from an environment variable (at runtime of the container, not to confuse with ARG and --build-arg at build-time of the image) which can be set when you start your container
Iw somewhere in your node app
// read the config file name from the environment variable
// and have a fallback if the environment variable is not defined
const configfilename = process.env.CONFIG_FILE || "config.json";
and when you start your container you can do
docker run --env CONFIG_FILE=prod-config.json YOURIMAGE
to set the environment variable. This way, you will have only one image.
A third possibility would be to not add your configs in the container at all, but load them from external volume that you mount when you run the container. If you have different volumes for diffent configs, you can again decide at startup, which volume to mount. As you can give your config file the same name on every volume, your app does not need to be aware of any environment variables, you just have to make sure, you use the correct path to your config file and all volumes have the same file structure.
Ie in your node app
const configfile = '/config/config.json';
and then you start your container mounting the correct config directory
docker run -v /host/path/to/prod-config:/config YOURIMAGE
I am currently using nodejs that is deployed in ebs on aws. I have a function that will write a pdf and then email it off but it says the file path can't be found. I've verified the project file seems to be /var/app/current/, but changing the reference of the file path doesn't seem to remove the error. Any idea how to go about fixing this?
The /var/app/current/ does not exist initially. Its only created at the very last stage of your deployment.
The deployment happens in /var/app/staging/ folder, and at the very last, once everything finishes, /var/app/staging/ is moved into /var/app/current/.
Thus, I would not recommend using absolute paths in your project or config files. Its better to use relative path or container_commands for config scripts:
The specified commands run as the root user, and are processed in alphabetical order by name. Container commands are run from the staging directory, where your source code is extracted prior to being deployed to the application server.
I need to inject env variables into my code.
I'm using azure pipelines to build my android app in react native.
I have set env variables in the build configuration and I have created a file called appcenter-post-clone.sh. The contents of this file are as follows:
ENV ADMIN_HOST= $ADMIN_HOST
And in my build configuration I have defined
ADMIN_HOST = https://example.com.
But I'm getting this error, [command]/bin/bash /Users/runner/runners/2.160.1/work/1/s/appcenter-post-clone.sh
ENV: https://example.com: No such file or directory. What I fail to understand here is, why is azure treating the value of my env variables as a file? How do I make this work?
The blunder I made here is, I should have used
ENV ADMIN_HOST=$ADMIN_HOST
Without the space. That solved it for me.
I'm deploying a node.js app on Heroku dyno and using config module that requires me to define a system variable NODE_CONFIG_DIR with the location of the config folder.
The config folder is located on my project's root.
I tried to define the system variable NODE_CONFIG_DIR using the following values, all failed:
./config
~/config
app/config
~/app/config
./app/config
$HOME/config
$HOME/app/config
I keep getting this error:
WARNING: No configurations found in configuration directory:app/config
(replace app/config with any of the values above)
I manage to set a system variable, but its value is not pointing the right place.
What is the correct way to refer to the root of my tree when using a system variable in Heroku?
Based on documentation - if config folder is in the root of your application you should not need to specify $NODE_CONFIG_DIR env variable.
From node-config documentation:
Node-config reads configuration files in the './config' directory for the running process, typically the application root. This can be overridden by setting the $NODE_CONFIG_DIR environment variable to the directory containing your configuration files. It can also be set from node, before loading Node-config:
process.env["NODE_CONFIG_DIR"] = __dirname + "/configDir/";
const config = require("config");
$NODE_CONFIG_DIR can be a full path from your root directory, or a relative path from the process if the value begins with ./ or ../.
You could use above code to set it from your node code.
You were close: /app is the correct path. You can verify it by running heroku run bash.
It was my bad...
Both answers are correct but didn't solve my issue.
The problem was that I used lowercase for my configuration file name while the NODE_ENV value was uppercase.