Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Docker configuration with Object Storage support #71

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .github/workflows/deploy-oss.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# reference:
# 1. https://github.com/docker/build-push-action/blob/master/docs/advanced/push-multi-registries.md
# 2. https://github.com/docker/build-push-action/blob/master/docs/advanced/share-image-jobs.md

name: Deploy to Production environment
on:
push:
tags:
- v*
env:
ARTIFACT_PATH: artifact.tar
BOX_NAME: api-service
BOX_URL: polyfiller/api-service

jobs:
deploy_docker_image:
name: Deploy Docker image
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v3

- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2

- name: Build Image
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64
tags: ${{ env.BOX_URL }}:latest
outputs: type=docker,dest=${{ env.ARTIFACT_PATH }}

- name: Pick Docker Compose
run: |
cat > .env <<EOF
${{ secrets.ENV_FILE }}
EOF
echo "${{ secrets.RCLONE_FILE }}" > config/rclone/rclone.conf
mkdir build
mv ${{ env.ARTIFACT_PATH }} docker-compose.yml .env start-docker.sh config/ build/

- name: Transport Image
uses: garygrossgarten/github-action-scp@release
with:
local: ./build
remote: /tmp/${{ env.BOX_NAME }}
host: ${{ secrets.HOST }}
username: ${{ secrets.USER }}
password: ${{ secrets.SSH_KEY }}

- name: Run Image
uses: garygrossgarten/github-action-ssh@release
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USER }}
password: ${{ secrets.SSH_KEY }}
command: |
cd /tmp/${{ env.BOX_NAME }}
mkdir -p ~/${{ env.BOX_NAME }}
mv docker-compose.yml .env start-docker.sh config/ ~/${{ env.BOX_NAME }}
cd ~/${{ env.BOX_NAME }}
chmod +x ./start-docker.sh
echo ${{ secrets.SSH_KEY }} | sudo -S ./start-docker.sh /tmp/${{ env.BOX_NAME }}/${{ env.ARTIFACT_PATH }}
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Reference: https://pnpm.io/docker#example-1-build-a-bundle-in-a-docker-container

FROM node:18-slim AS base
RUN apt-get update && \
apt-get install curl -y --no-install-recommends
COPY . /app
WORKDIR /app

FROM base AS prod-deps
RUN npm i --prod

FROM base AS build
RUN npm i
RUN npm run build

FROM base
COPY --from=prod-deps /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist
EXPOSE 3000
CMD ["npm", "start"]
139 changes: 139 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ Polyfiller is kindly supported by [JetBrains](https://www.jetbrains.com/?from=Po
- [FAQ](#faq)
- [What's the difference from polyfill.io](#whats-the-difference-from-polyfillio)
- [Hosting](#hosting)
- [Docker](#docker)
- [Install Docker in Cloud Server at first](#install-docker-in-cloud-server-at-first)
- [Simple container](#simple-container)
- [Composed services with Object Storage](#composed-services-with-object-storage)
- [1. Rclone config](#1-rclone-config)
- [2. Automatic deployment](#2-automatic-deployment)
- [Logo](#logo)
- [License](#license)
- [Feature names](#feature-names)
Expand Down Expand Up @@ -362,6 +368,139 @@ These two services are very much alike. In fact, `Polyfiller` depends on the lib
The server is built with support for both HTTP2 and HTTP. The environment variable `HTTP2=[true|false]` decides whether a HTTP2 server will be hosted or not.
If you use a load balancer and something like `nginx` in a reverse proxy setup, please know that `nginx` doesn't support HTTP2 via its proxy module, so you have to use HTTP1.1 there. Thankfully, it is as easy as setting `HTTP2=false` before launching the server and setting `HTTPS=false`.

#### Docker

> This guide has been tested in the deployment process of China mirror: https://polyfiller.kaiyuanshe.cn

##### Install Docker in Cloud Server at first

In the development environment, use installation script

```shell
curl -fsSL https://get.docker.com | sudo sh
```

add the current user to the `docker` user group

```shell
sudo gpasswd -a ${USER} docker
```

You need to press <kbd>CTRL</kbd> + <kbd>D</kbd> to log out of the session, then use SSH to log back into the system.

[Docker-install-script](https://github.com/docker/docker-install) says `It is not recommended to depend on this script for deployment to production systems`.
**So depend on your choice**.
Find more information in the [Docker install document](https://docs.docker.com/engine/install/).

Rclone use `FUSE` mount the Rclone's cloud storage systems, you need to install it.

In Debian(Ubuntu)

```shell
sudo apt install fuse3 -y
```

In CentOS

```shell
sudo yum install epel-release
sudo yum update
sudo yum install fuse3
```

In Fedora

```shell
sudo dnf install fuse3
```

In Arch

```shell
sudo pacman -Syu fuse3
```

##### Simple container

Run shown commands in the Project Root folder:

```shell
docker build -t polyfiller/api-service .
docker run --name polyfiller -e NODE_ENV=production -p 3000:3000 polyfiller/api-service
```

##### Composed services with Object Storage

###### 1. Rclone config

1. Write [Rclone config](https://rclone.org/install/) into `config/rclone/rclone.conf` file of your Project:

```ini
[azure]
type = azureblob
account = xxxx
key = xxxx
endpoint = https://xxx
```

How to configure quickly? Use `rclone config` command? It needs to know a lot of things. Open [Document](https://rclone.org/docs/), choose an instructions, like [Dropbox](https://rclone.org/dropbox/).

Look for

```ini
[remote]
app_key =
app_secret =
token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX_XXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

It is the configuration for Dropbox.

```ini
[dropbox]
type = dropbox
app_key = xxxxxxxxx
app_secret = xxxxxxxxx
token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX_XXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

If you use Dropbox, in `docker-compose.yml`:

```yaml
command: "mount azure:/ /polyfill-cache --allow-other --allow-non-empty --vfs-cache-mode writes"
```

It should be changed to:

```yml
command: "mount dropbox:/ /polyfill-cache --allow-other --allow-non-empty --vfs-cache-mode writes"
```

2. Run shown commands in the Project Root folder:

```shell
docker compose up -d
```

###### 2. Automatic deployment

1. Set GitHub Repository secrets:

| name | value |
| :-----------: | :-------------------------------: |
| `RCLONE_FILE` | rclone configuration file |
| `ENV_FILE` | `.env` file shown above |
| `HOST` | IP or Domain Name of Cloud Server |
| `USER` | Account Name of Cloud Server |
| `SSH_KEY` | SSH Private Key of Cloud Server |

2. Push a Git tag:

```shell
git tag v0.2.3-oss # the version number is the value of "version" field in "package.json"
git push origin --tags
```

## Logo

All credits go to [Andreas Mehlsen (@andreasbm)](https://github.com/andreasbm/) for the awesome logo design.
Expand Down
6 changes: 6 additions & 0 deletions config/rclone/rclone.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Detail document in https://rclone.org/install/ & https://rclone.org/docs/
[azure]
type = azureblob
account = xxxx
key = xxxx
endpoint = https://xxx
64 changes: 64 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
version: "3"

networks:
polyfiller:

services:
autoheal:
image: willfarrell/autoheal:1.2.0
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: always

polyfill-cache:
image: rclone/rclone:latest
environment:
- RCLONE_CONFIG=/config/rclone/rclone.conf # Path to the rclone config file inside the container
cap_add:
- SYS_ADMIN # Necessary for FUSE
- MKNOD # Necessary for FUSE
devices:
- "/dev/fuse" # Necessary for FUSE
security_opt:
- "apparmor:unconfined"
volumes:
- ./config/rclone:/config/rclone # Mount the local rclone config directory to the container
- ./polyfill-cache:/polyfill-cache:shared # Mount the local directory for the rclone mount
command: "mount azure:/ /polyfill-cache --allow-other --allow-non-empty --vfs-cache-mode writes"
restart: always

api-service:
depends_on:
- autoheal
- polyfill-cache
image: polyfiller/api-service
environment:
- NODE_ENV=production
volumes:
- ./polyfill-cache:/tmp/@wessberg/polyfiller
networks:
- polyfiller
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:3000/ || exit 1"]
interval: 3s
retries: 5
start_period: 30s
labels:
- autoheal=true
restart: always
logging:
driver: json-file
options:
max-size: 10m

caddy:
depends_on:
- api-service
image: caddy
ports:
- 80:80
- 443:443
networks:
- polyfiller
restart: always
command: caddy reverse-proxy --from polyfiller.app --to api-service:3000
8 changes: 3 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
"version": "npm run generate:all && git add .",
"release": "np --no-cleanup --no-yarn --no-tests",
"update:check": "npx npm-check-updates -x np --dep dev,prod",
"update:commit": "npx npm-check-updates -u -x np,find-up --dep dev,prod && npm update && npm install"
"update:commit": "npx npm-check-updates -u -x np,find-up --dep dev,prod && npm update && npm install",
"pack-image": "docker build -t polyfiller/api-service:latest .",
"container": "docker rm -f api-service && docker run --name api-service -p 3000:3000 -d polyfiller/api-service:latest"
},
"keywords": [
"polyfills",
Expand All @@ -48,7 +50,6 @@
"@typescript-eslint/parser": "5.48.2",
"@wessberg/di-compiler": "3.2.0",
"@rollup/plugin-json": "6.0.0",
"@wessberg/ts-config": "3.1.0",
"@wessberg/prettier-config": "1.0.0",
"ava": "5.1.1",
"eslint": "8.32.0",
Expand Down Expand Up @@ -93,6 +94,7 @@
"@wessberg/di": "2.1.0",
"@wessberg/pointer-events": "1.0.9",
"@wessberg/stringutil": "1.0.19",
"@wessberg/ts-config": "3.1.0",
"lit": "2.6.1",
"blob-polyfill": "5.0.20210201",
"browserslist": "4.21.5",
Expand Down
Loading