# Sysmaker Docker Support
###### tags: `Sysmaker` `Docker` `Dockerfile` `docker-compose`
[TOC]
## About Sysmaker
* We ars **Sysmaker team** from *EPL, NTHU*
* Find us [**`@Sysmaker.Org`**](https://sysmaker.org) & [**`@Sysmaker GitHub`**](https://github.com/sysmaker-org)
+ We haven't published our source code yet
+ However, our production docker images are available @[**Docker Hub**](https://hub.docker.com/u/sysmaker)
## About Docker
> **`TL;DR`** **Visit Sysmaker [*`GitHub Repo`*](https://github.com/Sysmaker-Org/Docker) to trace our code** [color=red]
* Run Sysmaker (refer @[`GitHub`](https://github.com/Sysmaker-Org/Sysmaker-Docker_Images#run) for further info)
1. `$ ./1-up.sh` (sysmaker/syamker-app & api)
2. `$ ./1-up.sh single` (sysmaker/sysmaker)
* The docker image categories we are offering now *(Apr 2020 ~)*
+ There are stable **`master`** branch and developing **`feature`** branch in our workflow
+ **`Image for Mainline`**
:::success
1. **`:master-*`**: the **testing passed** versions
2. **`:latest`**: the newest *`master-`* version
3. **`:prod`**: the newest *stable `master-` version* for mid-term production
4. **`:vXX.YY.ZZ`**: the *stable `prod` versions* which *deserve version tags* :D
:::
+ **`Image under Development`**
:::info
1. **`:dev`**: the newest *`feature-`* version (specific feature image is NOT provided)
:::
- :::warning
* <span style="color:red">**`sysmaker/sysmaker-env`** use **`:latest`** for both *`master-*`* and *`feature-*`* branches</span> (but still having `:dev`)
+ This is by design for GitLab CI so that we can always use the `latest` tag even when we're on the `feature branch`
+ Use **`master-*`** tags to make sure you're using the correct environment
:::
* In order to make use of our images, some `docker-compose*.yml`, `Dockerfile*`, and `*.conf` are provided as follows
+ *Dockerfile*
1. [**`sysmaker/sysmaker-env`**](#sysmakersysmaker-env)
2. [**`the rest`**](#sysmakersysmaker-sysmakersysmaker-app-and-sysmakersysmaker-api)
+ *docker-compose.yml*
1. [**`environment variables`**](#env)
2. [**`sysmaker/sysmaker (single)`**](#sysmakersysmaker-single)
3. [**`sysmaker/sysmaker-app&api (normal)`**](#sysmakersysmaker-app-and-sysmakersysmaker-api-normal)
+ *(Nginx) Configs*
1. [**`Angular (sysmaker-app)`**](#appconf)
2. [**`Sysmaker normal (APP + API + Nginx)`**](#normalhttpsconf)
3. [**`Sysmaker single`**](#singlehttpsconf)
4. [**`Cloudflare Proxy IP Restore`**](#restore-ipcloudflare)
* *CHANGELOG*
+ **`master-0012-4045ddb`~ `now`** [time=Apr 2, 2020] [color=red]
* Folder structure
+ ```bash=
├── 0-build.sh
├── 1-up.sh
├── 2-down.sh
├── 3-push.sh
│
├── .docker-compose.env.yml # for `sysmaker/sysmaker-env`
├── .Dockerfile-env
├── .env # specify base image versions
│
├── docker-compose.gitlab-ci.yml # for GitLab CI to build images
├── docker-compose.single.yml # single
├── docker-compose.yml # app and api (normal)
├── Dockerfile
│
└── misc
├── nginx-confd
│ ├── app.conf # for Nginx to serve Angular
│ ├── nginx.http.conf # just remove `https` part
│ ├── nginx.https.conf
│ ├── single.http.conf
│ └── single.https.conf
│
└── ssl
├── restore-ip.cloudflare
├── sysmaker.crt # Use your own SSL certificate
└── sysmaker.key # Ibid.
```
### Dockerfile
> `master-0012-4045ddb` ~ `now`
#### [**`sysmaker/sysmaker-env`**](https://github.com/Sysmaker-Org/Docker/blob/master/.Dockerfile-env)
```dockerfile=
ARG IMAGE_CYPRESS=cypress/base:12.16.1
FROM $IMAGE_CYPRESS
LABEL maintainer="LouisSung <ls@sysmaker.org>" \
description="Sysmaker environment for ci and build (with Cypress, NPM, and Docker)"
ARG IMAGE_CYPRESS
WORKDIR /sysmaker
COPY sysmaker/package*.json ./
COPY misc/pages/* ./pages/
RUN echo "Image: $IMAGE_CYPRESS" \
&& apt-get update && apt-get install -y --no-install-recommends \
bash bc curl jq git rsync tree libcanberra-gtk3-module \
apt-transport-https ca-certificates gnupg2 software-properties-common \
&& curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - \
&& add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" \
&& apt-get update && apt-get install -y --no-install-recommends \
docker-ce=5:19.03.8~3-0~debian-buster docker-ce-cli=5:19.03.8~3-0~debian-buster containerd.io \
&& curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \
&& chmod +x /usr/local/bin/docker-compose \
&& rm -rf /var/lib/apt/lists/* \
\
&& npm install --ignore-scripts --no-audit --loglevel info \
&& npm audit fix --ignore-scripts --verbose \
&& npm run postinstall \
&& $(npm bin)/cypress install
SHELL ["/bin/bash", "-c"]
CMD ["bash", "-c", "exit 0"]
```
#### [**`sysmaker/sysmaker`**, **`sysmaker/sysmaker-app`**, and **`sysmaker/sysmaker-api`**](https://github.com/Sysmaker-Org/Docker/blob/master/.Dockerfile-env)
```dockerfile=
# ===== default images =====
ARG IMAGE_SYSMAKER_ENV=sysmaker/sysmaker-env:latest
ARG IMAGE_NODE=node:lts-alpine
ARG IMAGE_NGINX=nginx:alpine
# ===== build stage =====
FROM $IMAGE_SYSMAKER_ENV AS base
LABEL sysmaker="build"
ARG IMAGE_SYSMAKER_ENV
WORKDIR /sysmaker/
COPY sysmaker/ misc/nginx-confd/app.conf ./
RUN echo "Image: $IMAGE_SYSMAKER_ENV" \
&& npm run sysmaker:build \
&& mv package-lock.json old-package-lock.json && mv node_modules/ old-node_modules/ \
&& find dist/apps/sysmaker \( -name '*.js' -o -name '*.css' \) -type f -exec gzip -9 -k "{}" \; \
\
&& npm install @nestjs/common @nestjs/core @nestjs/platform-express reflect-metadata rxjs tslib \
&& cp -r node_modules/ dist/apps/api/
# ===== APP =====
FROM $IMAGE_NGINX AS sysmaker-app
LABEL maintainer="LouisSung <ls@sysmaker.org>" \
description="Sysmaker APP" \
sysmaker="app"
COPY --from=base /sysmaker/dist/apps/sysmaker/ /usr/share/nginx/html/
COPY --from=base /sysmaker/app.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# ===== API =====
FROM $IMAGE_NODE AS sysmaker-api
LABEL maintainer="LouisSung <ls@sysmaker.org>" \
description="Sysmaker API" \
sysmaker="api"
WORKDIR /sysmaker/api/
COPY --from=base /sysmaker/dist/apps/api/ /sysmaker/api/
ENV port=80
EXPOSE 80
CMD ["node", "/sysmaker/api/main.js"]
# ===== SINGLE =====
FROM $IMAGE_NODE AS sysmaker-single
LABEL maintainer="LouisSung <ls@sysmaker.org>" \
description="Sysmaker" \
sysmaker="single"
WORKDIR /sysmaker/
COPY --from=base /sysmaker/dist/apps/sysmaker/ /usr/share/nginx/html/
COPY --from=base /sysmaker/dist/apps/api/ /sysmaker/api/
RUN apk update && apk add --no-cache nginx && mkdir -p /var/run/nginx
EXPOSE 80
EXPOSE 443
ENTRYPOINT []
CMD ["sh", "-c", "nginx & nohup node /sysmaker/api/main.js"]
```
### docker-compose.yml
> `master-0012-4045ddb` ~ `now`
#### [**`.env`**](https://github.com/Sysmaker-Org/Docker/blob/master/.env)
> save as an `.env` file and put in the same folder as `docker-compose.yml`
```bash=
# Nginx for APP: Latest + Alpine (https://hub.docker.com/_/nginx?tab=tags&page=1&name=-alpine)
VER_NGINX=1.17.9-alpine
# Node.js for API: LTS !! + Alpine (https://hub.docker.com/_/node?tab=tags&page=1&name=-alpine)
VER_NODE=12.16.1-alpine3.11
# Cypress for CI and build: Sync with Node.js version !! (https://github.com/cypress-io/cypress-docker-images/tree/master/base)
VER_CYPRESS=12.16.1
IMAGE_TAG=master-0012-4045ddb
```
#### [**`sysmaker/sysmaker`**](https://github.com/Sysmaker-Org/Docker/blob/master/docker-compose.single.yml) (single)
```yaml=
# Single Sysmaker image (APP & API in single image)
version: '3.7'
# ===== configs =====
x-images:
&images
IMAGE_NODE: node:${VER_NODE}
IMAGE_NGINX: nginx:${VER_NGINX}
# IMAGE_SYSMAKER_ENV: sysmaker/sysmaker-env:${IMAGE_TAG} # prefer using Docker Hub latest one
x-https:
&https
- ./misc/nginx-confd/single.https.conf:/etc/nginx/conf.d/default.conf:ro
- ./misc/ssl/:/etc/nginx/conf.d/ssl/:ro
x-http:
&http
- ./misc/nginx-confd/single.http.conf:/etc/nginx/conf.d/default.conf:ro
- ./misc/ssl/restore-ip.cloudflare:/etc/nginx/conf.d/ssl/restore-ip.cloudflare:ro
# ===== services =====
services:
sysmaker-single:
build:
context: .
target: sysmaker-single
args: *images
image: sysmaker/sysmaker:${IMAGE_TAG}
container_name: Sysmaker
hostname: Sysmaker
volumes: *http
ports:
- '80:80'
- '443:443'
```
#### [**`sysmaker/sysmaker-app`** and **`sysmaker/sysmaker-api`**](https://github.com/Sysmaker-Org/Docker/blob/master/docker-compose.yml) (normal)
```yaml=
# Normal Sysmaker images (APP + API + Nginx)
version: '3.7'
# ===== configs =====
x-images:
&images
IMAGE_NODE: node:${VER_NODE}
IMAGE_NGINX: nginx:${VER_NGINX}
# IMAGE_SYSMAKER_NPM_OR_NODE: sysmaker/sysmaker-npm:${IMAGE_TAG} # prefer Docker Hub one
x-https:
&https
- ./misc/nginx-confd/normal.https.conf:/etc/nginx/conf.d/default.conf:ro
- ./misc/ssl/:/etc/nginx/conf.d/ssl/:ro
x-http:
&http
- ./misc/nginx-confd/normal.http.conf:/etc/nginx/conf.d/default.conf:ro
- ./misc/ssl/restore-ip.cloudflare:/etc/nginx/conf.d/ssl/restore-ip.cloudflare:ro
# ===== services =====
services:
sysmaker-app:
build:
context: .
target: sysmaker-app
args: *images
image: sysmaker/sysmaker-app:${IMAGE_TAG}
container_name: Sysmaker-APP
hostname: Sysmaker-APP
networks:
- sysmaker-lan
sysmaker-api:
build:
context: .
target: sysmaker-api
args: *images
image: sysmaker/sysmaker-api:${IMAGE_TAG}
container_name: Sysmaker-API
hostname: Sysmaker-API
networks:
- sysmaker-lan
sysmaker-nginx:
image: nginx:${VER_NGINX}
container_name: Sysmaker-Nginx
hostname: Sysmaker-Nginx
volumes: *http
ports:
- '80:80'
- '443:443'
networks:
- sysmaker-lan
networks:
sysmaker-lan:
```
#### for [GitLab CI](https://github.com/Sysmaker-Org/Docker/blob/master/docker-compose.gitlab-ci.yml) to build images
```yaml=
# For GitLab to build production images during CI process (rarely change)
version: '3.7'
services:
sysmaker-app:
build:
context: .
target: sysmaker-app
image: sysmaker/sysmaker-app:${IMAGE_TAG}
sysmaker-api:
build:
context: .
target: sysmaker-api
image: sysmaker/sysmaker-api:${IMAGE_TAG}
sysmaker-single:
build:
context: .
target: sysmaker-single
image: sysmaker/sysmaker:${IMAGE_TAG}
```
### Configs
> `master-0012-4045ddb` ~ `now`
#### [**`app.conf`**](https://github.com/Sysmaker-Org/Docker/blob/master/misc/nginx-confd/app.conf)
```clike=
server {
listen 80;
gzip on;
gzip_static on;
gzip_min_length 4k;
gzip_vary on;
index index.html;
root /usr/share/nginx/html;
location / {
try_files $uri$args $uri$args/ /index.html;
}
}
```
#### [**`normal.http(s).conf`**](https://github.com/Sysmaker-Org/Docker/blob/master/misc/nginx-confd/normal.https.conf)
* **`https`**: *Uncomment`##`*; **`http`**: *Keep or Remove Lines*
```clike=
# Restore original ip from Cloudflare proxy
include conf.d/ssl/restore-ip.cloudflare;
# Deny requests that are not via our domains
server {
listen 80 default_server;
listen [::]:80 default_server;
## listen 443 default_server;
## listen [::]:443 default_server;
server_name _;
## ssl_certificate conf.d/ssl/sysmaker.crt;
## ssl_certificate_key conf.d/ssl/sysmaker.key;
return 412;
}
### Redirect to HTTPS
##server {
## listen 80;
## server_name *.sysmaker.org localhost;
## return 301 https://$host$request_uri; # redirect http:80 to https
##}
server {
## listen 443 ssl;
listen 80;
server_name *.sysmaker.org localhost;
## ssl_certificate conf.d/ssl/sysmaker.crt;
## ssl_certificate_key conf.d/ssl/sysmaker.key;
## error_page 497 https://$host$request_uri; # redirect http:443 to https
location ~ ^/api/v\d+/?.*$ {
proxy_pass http://Sysmaker-API;
}
location / {
proxy_pass http://Sysmaker-APP;
}
}
```
#### [**`single.http(s).conf`**](https://github.com/Sysmaker-Org/Docker/blob/master/misc/nginx-confd/single.https.conf)
```clike=
# Restore original ip from Cloudflare proxy
include conf.d/ssl/restore-ip.cloudflare;
# Deny requests that are not via our domains
server {
listen 80 default_server;
listen [::]:80 default_server;
## listen 443 default_server;
## listen [::]:443 default_server;
server_name _;
## ssl_certificate conf.d/ssl/sysmaker.crt;
## ssl_certificate_key conf.d/ssl/sysmaker.key;
return 412;
}
### Redirect to HTTPS
##server {
## listen 80;
## server_name *.sysmaker.org localhost;
## return 301 https://$host$request_uri; # redirect http:80 to https
##}
server {
## listen 443 ssl;
listen 80;
server_name *.sysmaker.org localhost;
## ssl_certificate conf.d/ssl/sysmaker.crt;
## ssl_certificate_key conf.d/ssl/sysmaker.key;
## error_page 497 https://$host$request_uri; # redirect http:443 to https
access_log /dev/stdout;
error_log /dev/stderr warn;
gzip on;
gzip_static on;
gzip_min_length 4k;
gzip_vary on;
index index.html;
root /usr/share/nginx/html;
location ~ ^/api/v\d+/?.*$ {
proxy_set_header Host $host;
proxy_pass http://localhost:3000;
proxy_redirect off;
}
location / {
try_files $uri$args $uri$args/ /index.html;
}
}
```
#### [**`restore-ip.cloudflare`**](https://github.com/Sysmaker-Org/Docker/blob/master/misc/ssl/restore-ip.cloudflare)
* Required only if you're using Cloudflare proxy
```bash=
# Get IP list here: https://www.cloudflare.com/ips/
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
# restore original IP
real_ip_header CF-Connecting-IP;
```