Featured image of post Build saleor dashboard docker image that accept environment variables

Build saleor dashboard docker image that accept environment variables

Saleor as mentioned in its landing page is

An open-source, GraphQL-first e-commerce platform delivering ultra-fast, dynamic and personalized shopping experiences.

Saleor is built as separate components

  • saleor-core which is the graphql api
  • saleor-dashboard which is the amdin area for the app
  • saleor-storefront which is the user facing part of the ecommerce platform

Usually, we as developers use the first 2 components as provided by the saleor team and build a custom storefront on top of it

The problem

The saleor-dashboard is a react app that is build as a static site in a docker container but to do that we have to provide the API_URI at the build time so for example if you have 4 environment development, stagging, test and production then you will need to build 4 different versions of the dashboard

i looked a round to see if someone else asked the same question and i found this issue #1592

My solution

The only answer on the above mentioned issue suggested that modifying the config.ts and index.html file would do the trick, so i will explain how you can do it manually, then feel free to automate the process

Get the dashboard code

clone the repo and checkout the version you need to build

1
git clone --depth 1 --branch <ref>  https://github.com/saleor/saleor.git

Config file

we will create a bash script env.sh that read the $API_URI env variable and generate a config javascript file, this script will run every time before the docker container started

notice that the docker container will serve the dashboard from a folder called dashboard that is why the script will generate the env file in the same folder

1
2
3
4
5
6
7
8
9
#!/bin/bash
target_file=./dashboard/env-config.js

touch $target_file
rm -rf $target_file

echo "window._env_ = {" >> $target_file
  echo "  API_URI: \"$API_URI\"," >> $target_file
echo "}" >> $target_file

The generated file should look like this

1
2
3
window._env_ = {
  API_URI: '<api-url-from-env>',
};

Modify src/index.html

Edit the main html file of the dashboard and add this script tag on the head

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, user-scalable=no"
    />
    <meta name="robots" content="noindex" />
    <title>Saleor e-commerce</title>
    <script src="/dashboard/env-config.js"></script>
    <!-- add this line-->
  </head>

  <body>
    <div id="dashboard-app"></div>
  </body>
</html>

Modify src/config.ts

now we will read the API_URI from the window object at the runtime instead of reading it from environment at build time

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import packageInfo from "../package.json";
import { SearchVariables } from "./hooks/makeSearch";
import { ListSettings, ListViews, Pagination } from "./types";

export const APP_MOUNT_URI = process.env.APP_MOUNT_URI || "/";
export const APP_DEFAULT_URI = "/";
// remove this line
export const API_URI = process.env.API_URI;

// add these 2 lines, typescript build would fail without the @ts-ignore
// @ts-ignore
export const API_URI = window._env_.API_URI;
....
....

Modify Dockerfile

for the docker file we need to do 2 things

  1. copy the env.sh script into the docker image root

  2. change the command to run the env.sh before starting the container

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
FROM node:14 as builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
ARG APP_MOUNT_URI
ARG API_URI
ARG STATIC_URL
ENV API_URI ${API_URI:-http://localhost:8000/graphql/}
ENV APP_MOUNT_URI ${APP_MOUNT_URI:-/dashboard/}
ENV STATIC_URL ${STATIC_URL:-/dashboard/}
RUN STATIC_URL=${STATIC_URL} API_URI=${API_URI} APP_MOUNT_URI=${APP_MOUNT_URI} npm run build

FROM nginx:stable
WORKDIR /app
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build/ /app/
# Add the following lines
COPY ./env.sh .
RUN chmod +x env.sh
CMD ["/bin/bash", "-c", "/app/env.sh && nginx -g \"daemon off;\""]

No you can build saleor-dashboard image that take the API_URI from your deployment environment

Note

For me to not repeat the above steps with every new version of the dashboard, i created a gitlab CI/CD pipeline to do this automatically for whatever version/tag/ref i specify but unfortunately this is something i can’t share

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy