I was setting up my CI/CD pipeline for deploying my payload app to app engine, where I dockerize the app, push it GCR and then deploy the image to app engine.
I have been successful in doing so. But the react app is making request to
http://localhost:3000/api/users/me
instead of
<PROVIDED HOSTNAME>/api/users/me
.
I've tried passing all the different environment variables
PAYLOAD_PUBLIC_PAYLOAD_URL
,
PAYLOAD_PUBLIC_PAYLOAD_API
and
PAYLOAD_URL
.
Production deployment throws fetch error
import { buildConfig } from "payload/config";
import path from "path";
import Categories from "./collections/Categories";
import Posts from "./collections/Posts";
import Tags from "./collections/Tags";
import Users from "./collections/Users";
import Media from "./collections/Media";
import { gcsAdapter } from "@payloadcms/plugin-cloud-storage/gcs";
import { cloudStorage } from "@payloadcms/plugin-cloud-storage";
let adapter = gcsAdapter({
options: {
// apiEndpoint: process.env.GCS_ENDPOINT,
projectId: process.env.GCS_PROJECT_ID,
},
bucket: process.env.GCS_BUCKET,
});
if (!process.env.PAYLOAD_PUBLIC_PAYLOAD_URL) {
// throw new Error("");
console.error("Cannot get the env variables");
}
export default buildConfig({
serverURL: process.env.PAYLOAD_PUBLIC_PAYLOAD_URL ?? "http://localhost:3000",
admin: {
user: Users.slug,
},
collections: [
Categories,
Posts,
Tags,
Users,
Media,
],
plugins: [
cloudStorage({
collections: {
media: {
adapter,
},
},
}),
],
typescript: {
outputFile: path.resolve(__dirname, "payload-types.ts"),
},
graphQL: {
schemaOutputFile: path.resolve(__dirname, "generated-schema.graphql"),
},
});
FROM node:18.8-alpine as base
FROM base as builder
WORKDIR /home/node/app
COPY package*.json ./
COPY . .
RUN yarn install
RUN yarn build
FROM base as runtime
ARG PAYLOAD_PUBLIC_PAYLOAD_URL="http://localhost"
ENV NODE_ENV=production
ENV PAYLOAD_CONFIG_PATH=dist/payload.config.js
ENV GCS_BUCKET=my-test-bucket-2002
ENV GCS_PROJECT_ID=payloadcms-test
ENV PAYLOAD_PUBLIC_PAYLOAD_URL=${PAYLOAD_PUBLIC_PAYLOAD_URL}
WORKDIR /home/node/app
COPY package*.json ./
COPY key.json ./key.json
ENV GOOGLE_APPLICATION_CREDENTIALS=./key.json
RUN yarn install --production
COPY --from=builder /home/node/app/dist ./dist
COPY --from=builder /home/node/app/build ./build
# EXPOSE 3000
CMD ["node", "dist/server.js"]
@dumbledore can you hard-code that serverURL field instead of using an environment variable and see if that works - just to test?
@Alessio 🍣 I did that as a temporary fix and it works. But I'm work on make it a reusable template with terraform for provisioning the infrastucture i.e creating storage bucket, provisioning mongodb database on atlas, enabling gcr, gae apis in gcp and a script that use github cli to add env secret to your git repo so that I can work on the schema and when I make a commit to the main branch the github actions deploy the new version of the app to app engine. In short, I want to automate all the tedious tasks before I start using it for something serious without going through the hassel setting things up.
This is the same issue I had with DevOps deployment to Azure.
The PAYLOAD_PUBLIC env cars have to be present when you run the “build” command to be compiled into the admin app
If you’re using the dockerfile you’ll need to set the env var inside there before build is called.
I figured that too and I used docker args to inject the variable from github secrets when building the docker image. But that didn't cut it, so I had to hardcode the url in the build config as a temporary fix.
I found I had to have a different dockerfile for each environment and set the bars in the dockerfile
I'm still trying make it work in a single environment i.e production. Once thats done then I'll move on working on provisioning different environment using IaaC and dedicate main and staging branch to deploy to those environment. But that's after I figure out this problem.
After the issues I had I opened up a discussion on github
https://github.com/payloadcms/payload/discussions/2288Did you hardcode the url in your config or did passing the environment variable at build time work for you?
I created a separate Dockerfile for each environment and hardcoded a
ENV PAYLOAD_PUBLIC_SERVER_URL=http....
in each just above the
npm install
line.
In DevOps Pipelines I then have a dynamic variable that selects which Dockerfile to build and publish based on the branch that triggered it.
Though I'm exposing the endpoint in the repo currently, but that's not what I want it to be. I want to be able to pass the
PAYLOAD_URL
via some secrets manager like github for one.
Basically we need the ability for the hosting environment variables to be passed to the admin (i.e. allow Admin to see/know about them at runtime rather than just at build time) ... not sure how feasible that is.
Thats the problem I'm trying to figure out
I think the safest solution at the moment is to use
.env.xxxxxx
files for all
PAYLOAD_PUBLIC_
vars and create a separate build script in package.json for each environment.
This way, you don't need to set the public vars in any hosting environment, you just have them all in the relevant file and that gets deployed alongside the app.
You can set private env vars in the hosting environment and use them in the Express server side of things still. This just means that some vars (like API keys) might require you to create a custom Express route that can use the private var, proxying the secured API.
I guess this would have been lot easier than what I just did. I added an additional step that during the CD creates
.env
that holds all the env, currently its just the
PAYLOAD_PUBLIC_
and feeds this to docker during the build.
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.