Skip to content
Snippets Groups Projects
Commit 5a258192 authored by Maarten de Waard's avatar Maarten de Waard :angel:
Browse files

Merge branch '102-dockerize-local-frontend-development' into 'main'

Resolve "Dockerize local frontend development"

Closes #102

See merge request stackspin/dashboard!65
parents 8e1d95bb 97648e46
No related branches found
No related tags found
No related merge requests found
Showing
with 133 additions and 163 deletions
...@@ -11,13 +11,11 @@ ...@@ -11,13 +11,11 @@
# production # production
/build /build
# local environment
/frontend/local.env
# misc # misc
.DS_Store .DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
*.swp *.swp
npm-debug.log* npm-debug.log*
......
...@@ -19,6 +19,7 @@ build-project: ...@@ -19,6 +19,7 @@ build-project:
stage: build-project stage: build-project
before_script: [] before_script: []
script: script:
- cd frontend
- echo "Building app" - echo "Building app"
- yarn install - yarn install
- echo "REACT_APP_API_URL=/api/v1" > .env - echo "REACT_APP_API_URL=/api/v1" > .env
...@@ -30,7 +31,7 @@ build-project: ...@@ -30,7 +31,7 @@ build-project:
expire_in: 1 hour expire_in: 1 hour
name: web-build name: web-build
paths: paths:
- web-build - frontend/web-build
.kaniko-build: .kaniko-build:
script: script:
...@@ -39,7 +40,7 @@ build-project: ...@@ -39,7 +40,7 @@ build-project:
- export CONTAINER_TAG=${CI_COMMIT_TAG:-${CI_COMMIT_REF_SLUG}} - export CONTAINER_TAG=${CI_COMMIT_TAG:-${CI_COMMIT_REF_SLUG}}
- /kaniko/executor --cache=true --context ${CI_PROJECT_DIR}/${DIRECTORY} --destination ${CI_REGISTRY_IMAGE}/${KANIKO_BUILD_IMAGENAME}:${CONTAINER_TAG} - /kaniko/executor --cache=true --context ${CI_PROJECT_DIR}/${DIRECTORY} --destination ${CI_REGISTRY_IMAGE}/${KANIKO_BUILD_IMAGENAME}:${CONTAINER_TAG}
build-fontend-container: build-frontend-container:
stage: build-container stage: build-container
image: image:
# We need a shell to provide the registry credentials, so we need to use the # We need a shell to provide the registry credentials, so we need to use the
...@@ -48,7 +49,7 @@ build-fontend-container: ...@@ -48,7 +49,7 @@ build-fontend-container:
entrypoint: [""] entrypoint: [""]
variables: variables:
KANIKO_BUILD_IMAGENAME: dashboard KANIKO_BUILD_IMAGENAME: dashboard
DIRECTORY: web-build DIRECTORY: frontend/web-build
before_script: before_script:
- cp deployment/Dockerfile $DIRECTORY - cp deployment/Dockerfile $DIRECTORY
- cp deployment/nginx.conf $DIRECTORY - cp deployment/nginx.conf $DIRECTORY
......
# Stackspin Dashboard # Stackspin Dashboard
This repo hosts the Stackspin Dashboard frontend code. This repo hosts the Stackspin Dashboard, both frontend and backend code.
The backend code is located at
<https://open.greenhost.net/stackspin/dashboard-backend>. ## Project structure
### Frontend
The frontend code lives in the `frontend` directory.
### Backend
The backend code lives in the `backend` directory. Apart from the dashboard
backend itself, it also contains a flask application that functions as the
identity provider, login, consent and logout endpoints for the OpenID Connect
(OIDC) process.
The application relies on the following components:
- **Hydra**: Hydra is an open source OIDC server.
It means applications can connect to Hydra to start a session with a user.
Hydra provides the application with the username
and other roles/claims for the application.
Hydra is developed by Ory and has security as one of their top priorities.
- **Kratos**: This is Identity Manager
and contains all the user profiles and secrets (passwords).
Kratos is designed to work mostly between UI (browser) and kratos directly,
over a public API endpoint.
Authentication, form-validation, etc. are all handled by Kratos.
Kratos only provides an API and not UI itself.
Kratos provides an admin API as well,
which is only used from the server-side flask app to create/delete users.
- **MariaDB**: The login application, as well as Hydra and Kratos, need to store data.
This is done in a MariaDB database server.
There is one instance with three databases.
As all databases are very small we do not foresee resource limitation problems.
If Hydra hits a new session/user, it has to know if this user has access.
To do so, the user has to login through a login application.
This application is developed by the Stackspin team (Greenhost)
and is part of this repository.
It is a Python Flask application
The application follows flows defined in Kratos,
and as such a lot of the interaction is done in the web-browser,
rather then server-side.
As a result,
the login application has a UI component which relies heavily on JavaScript.
As this is a relatively small application,
it is based on traditional Bootstrap + JQuery.
## Development environment ## Development environment
### Setup After this process is finished, the following will run in local docker containers:
Create a `.env` file in the project root directory: - the dashboard frontend
- the dashboard backend
cp .env.example .env The following will be available through proxies running in local docker containers and port-forwards:
and adjust the `REACT_APP_HYDRA_PUBLIC_URL` to the SSO URL of your cluster. - Hydra admin API
- Kratos admin API and public API
- The MariaDB database
#### `yarn start` These need to be available locally, because Kratos wants to run on the same
domain as the front-end that serves the login interface.
### Setup
Runs the app in the development mode. Please read through all subsections to set up your environment before
Open [http://localhost:3000](http://localhost:3000) to view it in the browser. attempting to run the dashboard locally.
The page will reload if you make edits. #### 1. Stackspin cluster
You will also see any lint errors in the console.
#### `yarn test` To develop the Dashboard, you need a Stackspin cluster that is set up as a
development environment. Follow the instructions [in the
dashboard-dev-overrides
repository](https://open.greenhost.net/stackspin/dashboard-dev-overrides#dashboard-dev-overrides)
in order to set up a development-capable cluster. The Dashboard, as well as
Kratos and Hydra, will be configured to point their endpoints to
`http://stackspin_proxy:8081` in that cluster. As a result, you can run
components using the `docker-compose.yml` file in this repository, and still log
into Stackspin applications that run on the cluster.
Launches the test runner in the interactive watch mode. #### 2. Environment for frontend
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests)
for more information.
#### `yarn build` The frontend needs to know where the backend API and hydra can be reached. To
configure it, create a `local.env` file in the `frontend` directory:
cp local.env.example local.env
and adjust the `REACT_APP_HYDRA_PUBLIC_URL` to the SSO URL of your cluster.
Builds the app for production to the `build` folder. #### 3. Setup hosts file
It correctly bundles React in production mode and optimizes the build
for the best performance.
The build is minified and the filenames include the hashes. The application will run on `http://stackspin_proxy`. Add the following line to
Your app is ready to be deployed! `/etc/hosts` to be able to access that from your browser:
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) ```
for more information. 127.0.0.1 stackspin_proxy
```
#### `yarn eject` #### 4. Kubernetes access
**Note: this is a one-way operation. Once you `eject`, you can’t go back!** The script needs you to have access to the Kubernetes cluster that runs
Stackspin. Point the `KUBECONFIG` environment variable to a kubectl config. Attention points:
If you aren’t satisfied with the build tool and configuration choices, * The kubeconfig will be mounted inside docker containers, so also make sure
you can `eject` at any time. This command will remove the single build dependency your Docker user can read it.
from your project. * The bind-mount done by docker might not work if the file pointed to is
part of a filesystem such as sshfs. In that case, copy the file to a local
drive first.
Instead, it will copy all the configuration files and the transitive dependencies ### Build and run
(webpack, Babel, ESLint, etc) right into your project so you have full control
over them.
All of the commands except `eject` will still work, but they will point to the
copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use `eject`. The curated feature set is suitable for After you've finished all setup steps, you can run everything using
small and middle deployments, and you shouldn’t feel obligated
to use this feature.
However we understand that this tool wouldn’t be useful
if you couldn’t customize it when you are ready for it.
## Learn More ./run_app.sh
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). This sets a few environment variables based on what is in your cluster
secrets, and run `docker compose up` to build and run all necessary components,
including a reverse proxy and the backend flask application.
# Stackspin dashboard backend
Backend for the [Stackspin dashboard](https://open.greenhost.net/stackspin/dashboard)
## Login application
Apart from the dashboard backend this repository contains a flask application
that functions as the identity provider, login, consent and logout endpoints
for the OpenID Connect (OIDC) process.
The application relies on the following components:
- **Hydra**: Hydra is an open source OIDC server.
It means applications can connect to Hydra to start a session with a user.
Hydra provides the application with the username
and other roles/claims for the application.
Hydra is developed by Ory and has security as one of their top priorities.
- **Kratos**: This is Identity Manager
and contains all the user profiles and secrets (passwords).
Kratos is designed to work mostly between UI (browser) and kratos directly,
over a public API endpoint.
Authentication, form-validation, etc. are all handled by Kratos.
Kratos only provides an API and not UI itself.
Kratos provides an admin API as well,
which is only used from the server-side flask app to create/delete users.
- **MariaDB**: The login application, as well as Hydra and Kratos, need to store data.
This is done in a MariaDB database server.
There is one instance with three databases.
As all databases are very small we do not foresee resource limitation problems.
If Hydra hits a new session/user, it has to know if this user has access.
To do so, the user has to login through a login application.
This application is developed by the Stackspin team (Greenhost)
and is part of this repository.
It is a Python Flask application
The application follows flows defined in Kratos,
and as such a lot of the interaction is done in the web-browser,
rather then server-side.
As a result,
the login application has a UI component which relies heavily on JavaScript.
As this is a relatively small application,
it is based on traditional Bootstrap + JQuery.
# Development
To develop the Dashboard,
you need a Stackspin cluster that is set up as a development environment.
Follow the instructions [in the dashboard-dev-overrides
repository](https://open.greenhost.net/stackspin/dashboard-dev-overrides#dashboard-dev-overrides)
in order to set up a development-capable cluster.
The end-points for the Dashboard,
as well as Kratos and Hydra, will point to `http://stackspin_proxy:8081` in that cluster.
As a result, you can run components using the `docker-compose` file in
this repository, and still log into Stackspin applications that run on the cluster.
## Setting up the local development environment
After this process is finished, the following will run locally:
- The [dashboard](https://open.greenhost.net/stackspin/dashboard)
- The
[dashboard-backend](https://open.greenhost.net/stackspin/dashboard-backend)
The following will be available locally through a proxy and port-forwards:
- Hydra admin
- Kratos admin and public
- The MariaDB database connections
These need to be available locally, because Kratos wants to run on the same
domain as the front-end that serves the login interface.
### 1. Setup hosts file
The application will run on `http://stackspin_proxy`. Add the following line to
`/etc/hosts` to be able to access that from your browser:
```
127.0.0.1 stackspin_proxy
```
### 2. Kubernetes access
The script needs you to have access to the Kubernetes cluster that runs
Stackspin. Point the `KUBECONFIG` environment variable to a kubectl config. That
kubeconfig will be mounted inside docker containers, so also make sure your
Docker user can read it.
### 3. Run it all
Now, run this script that sets a few environment variables based on what is in
your cluster secrets, and starts `docker-compose` to start a reverse proxy as
well as the flask application in this repository.
```
./run_app.sh
```
### 4. Front-end developmenet
Start the [dashboard front-end app](https://open.greenhost.net/stackspin/dashboard/#yarn-start).
version: '3' version: "3"
services: services:
frontend:
build:
context: ./frontend
working_dir: "/home/node/app"
env_file: ./frontend/local.env
ports:
- "3000:3000"
# command: "yarn start"
stackspin_proxy: stackspin_proxy:
image: nginx:1.23.2 image: nginx:1.23.1
ports: ports:
- "8081:8081" - "8081:8081"
volumes: volumes:
- ./proxy/default.conf:/etc/nginx/conf.d/default.conf - ./backend/proxy/default.conf:/etc/nginx/conf.d/default.conf
depends_on: depends_on:
- kube_port_kratos_public - kube_port_kratos_public
- flask_app - flask_app
flask_app: flask_app:
build: . build:
context: ./backend
environment: environment:
- FLASK_APP=app.py - FLASK_APP=app.py
- FLASK_ENV=development - FLASK_ENV=development
...@@ -39,13 +48,13 @@ services: ...@@ -39,13 +48,13 @@ services:
- "5000:5000" - "5000:5000"
user: "${KUBECTL_UID}:${KUBECTL_GID}" user: "${KUBECTL_UID}:${KUBECTL_GID}"
volumes: volumes:
- .:/app - ./backend:/app
- "$KUBECONFIG:/.kube/config" - "$KUBECONFIG:/.kube/config"
depends_on: depends_on:
- kube_port_mysql - kube_port_mysql
entrypoint: ["bash", "-c", "flask run --host $$(hostname -i)"] entrypoint: ["bash", "-c", "flask run --host $$(hostname -i)"]
kube_port_kratos_admin: kube_port_kratos_admin:
image: bitnami/kubectl:1.25.3 image: bitnami/kubectl:1.25.2
user: "${KUBECTL_UID}:${KUBECTL_GID}" user: "${KUBECTL_UID}:${KUBECTL_GID}"
expose: expose:
- 8000 - 8000
...@@ -53,7 +62,7 @@ services: ...@@ -53,7 +62,7 @@ services:
- "$KUBECONFIG:/.kube/config" - "$KUBECONFIG:/.kube/config"
entrypoint: ["bash", "-c", "kubectl -n stackspin port-forward --address $$(hostname -i) service/kratos-admin 8000:80"] entrypoint: ["bash", "-c", "kubectl -n stackspin port-forward --address $$(hostname -i) service/kratos-admin 8000:80"]
kube_port_hydra_admin: kube_port_hydra_admin:
image: bitnami/kubectl:1.25.3 image: bitnami/kubectl:1.25.2
user: "${KUBECTL_UID}:${KUBECTL_GID}" user: "${KUBECTL_UID}:${KUBECTL_GID}"
expose: expose:
- 4445 - 4445
...@@ -61,7 +70,7 @@ services: ...@@ -61,7 +70,7 @@ services:
- "$KUBECONFIG:/.kube/config" - "$KUBECONFIG:/.kube/config"
entrypoint: ["bash", "-c", "kubectl -n stackspin port-forward --address $$(hostname -i) service/hydra-admin 4445:4445"] entrypoint: ["bash", "-c", "kubectl -n stackspin port-forward --address $$(hostname -i) service/hydra-admin 4445:4445"]
kube_port_kratos_public: kube_port_kratos_public:
image: bitnami/kubectl:1.25.3 image: bitnami/kubectl:1.25.2
user: "${KUBECTL_UID}:${KUBECTL_GID}" user: "${KUBECTL_UID}:${KUBECTL_GID}"
ports: ports:
- "8080:8080" - "8080:8080"
...@@ -69,9 +78,9 @@ services: ...@@ -69,9 +78,9 @@ services:
- 8080 - 8080
volumes: volumes:
- "$KUBECONFIG:/.kube/config" - "$KUBECONFIG:/.kube/config"
entrypoint: ["bash", "-c", "kubectl -n stackspin port-forward --address $$(hostname -i) service/kratos-public 8080:80"] entrypoint: ["bash", "-c", "kubectl -n stackspin port-forward --address 0.0.0.0 service/kratos-public 8080:80"]
kube_port_mysql: kube_port_mysql:
image: bitnami/kubectl:1.25.3 image: bitnami/kubectl:1.25.2
user: "${KUBECTL_UID}:${KUBECTL_GID}" user: "${KUBECTL_UID}:${KUBECTL_GID}"
expose: expose:
- 3306 - 3306
......
File moved
File moved
File moved
File moved
FROM node:18
ADD . .
RUN yarn install
ENV NODE_OPTIONS="--openssl-legacy-provider"
CMD yarn start
File moved
File moved
File moved
File moved
File moved
File moved
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment