mirror of
https://github.com/Eugeny/tabby-web.git
synced 2025-06-08 05:29:52 +00:00
a unified docker image
This commit is contained in:
parent
e1b0d01ac3
commit
34ac0781c2
49
.github/workflows/docker.yml
vendored
Normal file
49
.github/workflows/docker.yml
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
name: Docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '25 12 * * *'
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
# Publish semver tags as releases.
|
||||||
|
tags: [ 'v*.*.*' ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
IMAGE_NAME: eugeny/tabby-web
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Log into registry ${{ env.REGISTRY }}
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
||||||
|
with:
|
||||||
|
build-args: EXTRA_DEPS=gcsfs
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
56
Dockerfile
Normal file
56
Dockerfile
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM node:12-alpine AS frontend-build
|
||||||
|
WORKDIR /app
|
||||||
|
COPY frontend/package.json frontend/yarn.lock ./
|
||||||
|
RUN yarn
|
||||||
|
COPY frontend/webpack* frontend/tsconfig.json ./
|
||||||
|
COPY frontend/assets assets
|
||||||
|
COPY frontend/src src
|
||||||
|
COPY frontend/theme theme
|
||||||
|
RUN yarn run build
|
||||||
|
RUN yarn run build:server
|
||||||
|
|
||||||
|
FROM node:12-alpine AS frontend
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=frontend-build /app/build build
|
||||||
|
COPY --from=frontend-build /app/build-server build-server
|
||||||
|
COPY frontend/package.json .
|
||||||
|
|
||||||
|
CMD ["npm", "start"]
|
||||||
|
|
||||||
|
# ----
|
||||||
|
|
||||||
|
FROM python:3.7-alpine AS build-backend
|
||||||
|
ARG EXTRA_DEPS
|
||||||
|
|
||||||
|
RUN apk add build-base musl-dev libffi-dev openssl-dev mariadb-dev
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
RUN pip install -U setuptools 'cryptography>=3.0,<3.1' poetry==1.1.7
|
||||||
|
COPY backend/pyproject.toml backend/poetry.lock ./
|
||||||
|
RUN poetry config virtualenvs.path /venv
|
||||||
|
RUN poetry install --no-dev --no-ansi --no-interaction
|
||||||
|
RUN poetry run pip install -U setuptools $EXTRA_DEPS
|
||||||
|
|
||||||
|
COPY backend/manage.py backend/gunicorn.conf.py ./
|
||||||
|
COPY backend/tabby tabby
|
||||||
|
COPY --from=frontend /app/build /frontend
|
||||||
|
|
||||||
|
ARG BUNDLED_TABBY=1.0.163
|
||||||
|
|
||||||
|
RUN FRONTEND_BUILD_DIR=/frontend /venv/*/bin/python ./manage.py collectstatic --noinput
|
||||||
|
RUN FRONTEND_BUILD_DIR=/frontend /venv/*/bin/python ./manage.py add_version ${BUNDLED_TABBY}
|
||||||
|
|
||||||
|
FROM python:3.7-alpine AS backend
|
||||||
|
|
||||||
|
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.9.0/wait /wait
|
||||||
|
RUN chmod +x /wait
|
||||||
|
|
||||||
|
RUN apk add mariadb-connector-c
|
||||||
|
|
||||||
|
COPY --from=build-backend /app /app
|
||||||
|
COPY --from=build-backend /venv /venv
|
||||||
|
|
||||||
|
COPY backend/start.sh backend/manage.sh /
|
||||||
|
RUN chmod +x /start.sh /manage.sh
|
||||||
|
CMD ["/start.sh"]
|
25
README.md
25
README.md
@ -16,27 +16,30 @@ Tabby Web serves the [Tabby Terminal](https://github.com/Eugeny/tabby) as a web
|
|||||||
* A database server supported by Django (MariaDB, Postgres, SQLite, etc.)
|
* A database server supported by Django (MariaDB, Postgres, SQLite, etc.)
|
||||||
* Storage for distribution files - local, S3, GCS or others supported by `fsspec`
|
* Storage for distribution files - local, S3, GCS or others supported by `fsspec`
|
||||||
|
|
||||||
# Using Docker images
|
# Quickstart (using `docker-compose`)
|
||||||
|
|
||||||
Tabby Web consists of two Docker images - `backend` and `frontend`. See an example set up in `docker-compose.yml`
|
You'll need:
|
||||||
|
|
||||||
|
* OAuth credentials from GitHub, GitLab, Google or Microsoft for authentication.
|
||||||
|
* For SSH and Telnet: a [`tabby-connection-gateway`](https://github.com/Eugeny/tabby-connection-gateway) to forward traffic.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -e SOCIAL_AUTH_GITHUB_KEY=xxx -e SOCIAL_AUTH_GITHUB_SECRET=yyy
|
||||||
|
```
|
||||||
|
|
||||||
|
will start Tabby Web on port 9090 with MariaDB as a storage backend.
|
||||||
|
|
||||||
|
For SSH and Telnet, once logged in, enter your connection gateway address and auth token in the settings.
|
||||||
|
|
||||||
## Environment variables
|
## Environment variables
|
||||||
|
|
||||||
### Frontend
|
|
||||||
|
|
||||||
* `BACKEND_URL` (required if running the backend in a separate Docker container).
|
|
||||||
* `WEB_CONCURRENCY`
|
|
||||||
|
|
||||||
### Backend
|
|
||||||
|
|
||||||
* `DATABASE_URL` (required).
|
* `DATABASE_URL` (required).
|
||||||
* `FRONTEND_URL`
|
|
||||||
* `APP_DIST_STORAGE`: a `file://`, `s3://`, or `gcs://` URL to store app distros in.
|
* `APP_DIST_STORAGE`: a `file://`, `s3://`, or `gcs://` URL to store app distros in.
|
||||||
* `SOCIAL_AUTH_*_KEY` & `SOCIAL_AUTH_*_SECRET`: social login credentials, supported providers are `GITHUB`, `GITLAB`, `MICROSOFT_GRAPH` and `GOOGLE_OAUTH2`.
|
* `SOCIAL_AUTH_*_KEY` & `SOCIAL_AUTH_*_SECRET`: social login credentials, supported providers are `GITHUB`, `GITLAB`, `MICROSOFT_GRAPH` and `GOOGLE_OAUTH2`.
|
||||||
|
|
||||||
## Adding Tabby app versions
|
## Adding Tabby app versions
|
||||||
|
|
||||||
* `docker-compose run backend ./manage.py add_version 1.0.156-nightly.2`
|
* `docker-compose run tabby /manage.sh add_version 1.0.163`
|
||||||
|
|
||||||
# Development setup
|
# Development setup
|
||||||
|
|
||||||
|
@ -1 +1,2 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
|
public
|
||||||
|
4
backend/manage.sh
Normal file
4
backend/manage.sh
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
/wait
|
||||||
|
cd /app
|
||||||
|
/venv/*/bin/python ./manage.py $@
|
@ -1,4 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
/wait
|
||||||
cd /app
|
cd /app
|
||||||
./manage.py migrate
|
/venv/*/bin/python ./manage.py migrate
|
||||||
gunicorn
|
/venv/*/bin/gunicorn
|
||||||
|
@ -42,7 +42,7 @@ class ChooseGatewayViewSet(RetrieveModelMixin, GenericViewSet):
|
|||||||
gateways = list(self.queryset)
|
gateways = list(self.queryset)
|
||||||
random.shuffle(gateways)
|
random.shuffle(gateways)
|
||||||
if not len(gateways):
|
if not len(gateways):
|
||||||
raise NotFound()
|
raise NoGatewaysError()
|
||||||
|
|
||||||
loop = asyncio.new_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
try:
|
try:
|
||||||
|
@ -12,12 +12,12 @@ class IndexView(APIView):
|
|||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
if settings.FRONTEND_URL:
|
if settings.FRONTEND_URL:
|
||||||
return HttpResponseRedirect(settings.FRONTEND_URL)
|
return HttpResponseRedirect(settings.FRONTEND_URL)
|
||||||
return static.serve(request, 'index.html', document_root=str(settings.FRONTEND_BUILD_DIR))
|
return static.serve(request, 'index.html', document_root=str(settings.STATIC_ROOT))
|
||||||
|
|
||||||
|
|
||||||
class TerminalView(APIView):
|
class TerminalView(APIView):
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
response = static.serve(request, 'terminal.html', document_root=str(settings.FRONTEND_BUILD_DIR))
|
response = static.serve(request, 'terminal.html', document_root=str(settings.STATIC_ROOT))
|
||||||
response['X-Frame-Options'] = 'SAMEORIGIN'
|
response['X-Frame-Options'] = 'SAMEORIGIN'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -9,8 +9,6 @@ load_dotenv()
|
|||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
FRONTEND_BUILD_DIR = BASE_DIR / '../frontend/build'
|
|
||||||
|
|
||||||
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY', 'django-insecure')
|
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY', 'django-insecure')
|
||||||
DEBUG = bool(os.getenv('DEBUG', False))
|
DEBUG = bool(os.getenv('DEBUG', False))
|
||||||
|
|
||||||
@ -135,11 +133,6 @@ LOGGING = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
|
||||||
if FRONTEND_BUILD_DIR.exists():
|
|
||||||
STATICFILES_DIRS = [FRONTEND_BUILD_DIR]
|
|
||||||
STATIC_ROOT = BASE_DIR / 'public'
|
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
CSRF_USE_SESSIONS = False
|
CSRF_USE_SESSIONS = False
|
||||||
@ -172,6 +165,7 @@ SOCIAL_AUTH_PIPELINE = (
|
|||||||
|
|
||||||
APP_DIST_STORAGE = os.getenv('APP_DIST_STORAGE', 'file://' + str(BASE_DIR / 'app-dist'))
|
APP_DIST_STORAGE = os.getenv('APP_DIST_STORAGE', 'file://' + str(BASE_DIR / 'app-dist'))
|
||||||
NPM_REGISTRY = os.getenv('NPM_REGISTRY', 'https://registry.npmjs.org').rstrip('/')
|
NPM_REGISTRY = os.getenv('NPM_REGISTRY', 'https://registry.npmjs.org').rstrip('/')
|
||||||
|
FRONTEND_BUILD_DIR = Path(os.getenv('FRONTEND_BUILD_DIR', BASE_DIR / '../frontend/build'))
|
||||||
|
|
||||||
FRONTEND_URL = None
|
FRONTEND_URL = None
|
||||||
BACKEND_URL = None
|
BACKEND_URL = None
|
||||||
@ -229,6 +223,12 @@ else:
|
|||||||
GITHUB_ELIGIBLE_SPONSORSHIPS = []
|
GITHUB_ELIGIBLE_SPONSORSHIPS = []
|
||||||
|
|
||||||
|
|
||||||
|
STATIC_URL = '/static/'
|
||||||
|
if FRONTEND_BUILD_DIR.exists():
|
||||||
|
STATICFILES_DIRS = [FRONTEND_BUILD_DIR]
|
||||||
|
STATIC_ROOT = BASE_DIR / 'public'
|
||||||
|
|
||||||
|
|
||||||
if FRONTEND_URL:
|
if FRONTEND_URL:
|
||||||
CORS_ALLOWED_ORIGINS = [FRONTEND_URL]
|
CORS_ALLOWED_ORIGINS = [FRONTEND_URL]
|
||||||
CORS_ALLOW_CREDENTIALS = True
|
CORS_ALLOW_CREDENTIALS = True
|
||||||
|
21
docker-compose.split.yml
Normal file
21
docker-compose.split.yml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
build: frontend
|
||||||
|
ports:
|
||||||
|
- 9090:80
|
||||||
|
environment:
|
||||||
|
- PORT=80
|
||||||
|
- BACKEND_URL=http://localhost:9091
|
||||||
|
backend:
|
||||||
|
build: backend
|
||||||
|
ports:
|
||||||
|
- 9091:80
|
||||||
|
volumes:
|
||||||
|
- ./app-dist:/app-dist
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL
|
||||||
|
- PORT=80
|
||||||
|
- FRONTEND_URL=http://localhost:9090
|
||||||
|
- ENABLE_HOMEPAGE=False
|
||||||
|
- DEBUG=False
|
||||||
|
- APP_DIST_STORAGE=file:///app-dist
|
@ -1,21 +1,26 @@
|
|||||||
services:
|
services:
|
||||||
frontend:
|
tabby:
|
||||||
build: frontend
|
build: .
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
ports:
|
ports:
|
||||||
- 9090:80
|
- 9090:80
|
||||||
environment:
|
|
||||||
- PORT=80
|
|
||||||
- BACKEND_URL=http://localhost:9091
|
|
||||||
backend:
|
|
||||||
build: backend
|
|
||||||
ports:
|
|
||||||
- 9091:80
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./app-dist:/app-dist
|
- ./app-dist:/app-dist
|
||||||
environment:
|
environment:
|
||||||
- DATABASE_URL
|
- DATABASE_URL=mysql://root:123@db/tabby
|
||||||
- PORT=80
|
- PORT=80
|
||||||
- FRONTEND_URL=http://localhost:9090
|
|
||||||
- ENABLE_HOMEPAGE=False
|
- ENABLE_HOMEPAGE=False
|
||||||
- DEBUG=False
|
- DEBUG=False
|
||||||
- APP_DIST_STORAGE=file:///app-dist
|
- APP_DIST_STORAGE=file:///app-dist
|
||||||
|
- WAIT_HOSTS=db:3306
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: mariadb:10.7.1
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
MARIADB_DATABASE: tabby
|
||||||
|
MARIADB_USER: user
|
||||||
|
MARIADB_PASSWORD: 123
|
||||||
|
MYSQL_ROOT_PASSWORD: 123
|
||||||
|
Loading…
x
Reference in New Issue
Block a user