diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..735a8b4f
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+web/node_modules/
\ No newline at end of file
diff --git a/.github/semantic.yml b/.github/semantic.yml
new file mode 100644
index 00000000..e8ac80b3
--- /dev/null
+++ b/.github/semantic.yml
@@ -0,0 +1,12 @@
+# Always validate the PR title AND all the commits
+titleAndCommits: true
+# Require at least one commit to be valid
+# this is only relevant when using commitsOnly: true or titleAndCommits: true,
+# which validate all commits by default
+anyCommit: true
+# Allow use of Merge commits (eg on github: "Merge branch 'master' into feature/ride-unicorns")
+# this is only relevant when using commitsOnly: true (or titleAndCommits: true)
+allowMergeCommits: false
+# Allow use of Revert commits (eg on github: "Revert "feat: ride unicorns"")
+# this is only relevant when using commitsOnly: true (or titleAndCommits: true)
+allowRevertCommits: false
\ No newline at end of file
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 00000000..2cb51437
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,45 @@
+name: Build
+
+on:
+ push:
+ branches:
+ - "*"
+ pull_request:
+ branches:
+ - "*"
+
+jobs:
+ frontend:
+ name: Front-end build
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ with:
+ node-version: '14.17.0'
+ - run: yarn install && CI=false yarn run build
+ working-directory: ./web
+
+ backend:
+ name: Back-end build
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-go@v2
+ with:
+ go-version: '^1.16.5'
+ - run: go version
+
+ - name: Build
+ run: |
+ go build -race -ldflags "-extldflags '-static'"
+ working-directory: ./
+
+ docker:
+ name: Docker compose
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ - name: Start containers
+ run: docker-compose up
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..afa9c147
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,65 @@
+name: Release
+
+on: [push, pull_request]
+
+jobs:
+ frontend:
+ name: Front-end build
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ with:
+ node-version: '14.17.0'
+ - run: yarn install && CI=false yarn run build
+ working-directory: ./web
+
+ backend:
+ name: Back-end build
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-go@v2
+ with:
+ go-version: '^1.16.5'
+
+ - name: Build
+ run: |
+ go build -race -ldflags "-extldflags '-static'"
+ working-directory: ./
+
+ release:
+ name: Release
+ runs-on: ubuntu-latest
+ needs: [frontend, backend]
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Setup Node.js
+ uses: actions/setup-node@v2
+ with:
+ node-version: 12
+ - name: Release
+ run: yarn global add semantic-release@17.4.4 && semantic-release
+ env:
+ GH_TOKEN: ${{ secrets.GH_TOKEN }}
+
+ publish:
+ name: Publish
+ runs-on: ubuntu-latest
+ needs: release
+ steps:
+ - name: Check out the repo
+ uses: actions/checkout@v2
+ - name: Log in to Docker Hub
+ uses: docker/login-action@v1
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_PASSWORD }}
+ - name: Push to Docker Hub
+ uses: docker/build-push-action@v2
+ with:
+ push: true
+ tags: shiluo/casdoor:latest
\ No newline at end of file
diff --git a/.releaserc.json b/.releaserc.json
new file mode 100644
index 00000000..ae3f3e74
--- /dev/null
+++ b/.releaserc.json
@@ -0,0 +1,22 @@
+{
+ "debug": true,
+ "branches": [
+ "+([0-9])?(.{+([0-9]),x}).x",
+ {
+ "name": "rc"
+ },
+ {
+ "name": "beta",
+ "prerelease": true
+ },
+ {
+ "name": "alpha",
+ "prerelease": true
+ }
+ ],
+ "plugins": [
+ "@semantic-release/commit-analyzer",
+ "@semantic-release/release-notes-generator",
+ "@semantic-release/github"
+ ]
+}
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 8cb65a41..62d2d32b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,25 +1,19 @@
-FROM golang:1.17-rc-buster
-WORKDIR /casdoor
-COPY ./ /casdoor
-RUN go env -w CGO_ENABLED=0 GOPROXY=https://goproxy.io,direct GOOS=linux GOARCH=amd64 \
- && apt update && apt install sudo \
- && wget https://nodejs.org/dist/v12.22.0/node-v12.22.0-linux-x64.tar.gz \
- && sudo tar xf node-v12.22.0-linux-x64.tar.gz \
- && sudo apt install wait-for-it
-ENV PATH=$PATH:/casdoor/node-v12.22.0-linux-x64/bin
-RUN npm install -g yarn \
- && cd web \
- && yarn install \
- && yarn run build \
- && rm -rf node_modules \
- && cd /casdoor \
- && go build main.go
-FROM alpine:3.7
-COPY --from=0 /casdoor /
-COPY --from=0 /usr/bin/wait-for-it /
-RUN set -eux \
- && sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
- && apk update \
- && apk upgrade \
- && apk add bash
-CMD ./wait-for-it db:3306 && ./main
+FROM golang:1.16 AS BACK
+WORKDIR /go/src/casdoor
+COPY . .
+RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o server . \
+ && apt update && apt install wait-for-it && chmod +x /usr/bin/wait-for-it
+
+FROM node:14.17.4 AS FRONT
+WORKDIR /web
+COPY ./web .
+RUN npm install && npm run build
+
+FROM alpine:latest
+LABEL MAINTAINER="https://casdoor.org/"
+
+COPY --from=BACK /go/src/casdoor/ ./
+COPY --from=BACK /usr/bin/wait-for-it ./
+RUN mkdir -p web/build && apk add --no-cache bash coreutils
+COPY --from=FRONT /web/build /web/build
+ENTRYPOINT ["./wait-for-it", "db:3306 ", "--", "./server"]
\ No newline at end of file
diff --git a/README.md b/README.md
index 4cde7b67..84116e5f 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,25 @@
-Casdoor
-====
-
-[](https://goreportcard.com/report/github.com/casbin/casdoor) [](https://github.com/casbin/casdoor/issues) [](https://github.com/casbin/casdoor/stargazers) [](https://github.com/casbin/casdoor/network)
-
-Casdoor is a UI-first centralized authentication / Single-Sign-On (SSO) platform based on OAuth 2.0 / OIDC.
+