├── .github ├── CODEOWNERS ├── renovate.json └── workflows │ └── build.yml ├── .gitignore ├── compose.yaml ├── README.md └── .env.example /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @gabe565 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | data/ 3 | .env 4 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>gabe565/renovate-config" 5 | ], 6 | "automerge": true, 7 | "regexManagers": [ 8 | { 9 | "fileMatch": ["^\\.github/workflows/"], 10 | "matchStringsStrategy": "combination", 11 | "matchStrings": [ 12 | "\\s+OBICO_REPO: (?.+)", 13 | "\\s+OBICO_BRANCH: (?.+)\\n\\s+OBICO_REF: (?.+)" 14 | ], 15 | "packageNameTemplate": "https://github.com/{{depName}}", 16 | "datasourceTemplate": "git-refs" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | collectstatic: 3 | image: ghcr.io/gabe565/obico/web 4 | env_file: 5 | - .env 6 | command: [python, manage.py, collectstatic, --verbosity=2, --noinput, --link] 7 | volumes: 8 | - ./data/data:/data 9 | - ./data/media:/app/static_build/media 10 | - static:/app/static_build 11 | 12 | migrate: 13 | extends: 14 | service: collectstatic 15 | command: [python, manage.py, migrate] 16 | 17 | web: 18 | extends: 19 | service: collectstatic 20 | ports: 21 | - "3334:3334" 22 | depends_on: &depends 23 | collectstatic: 24 | condition: service_completed_successfully 25 | migrate: 26 | condition: service_completed_successfully 27 | ml_api: 28 | condition: service_started 29 | command: [python, manage.py, runserver, --noreload, 0.0.0.0:3334] 30 | restart: unless-stopped 31 | 32 | tasks: 33 | extends: 34 | service: collectstatic 35 | hostname: tasks 36 | depends_on: *depends 37 | restart: unless-stopped 38 | command: 39 | - celery 40 | - --app=config 41 | - worker 42 | - --beat 43 | - --loglevel=info 44 | - --concurrency=2 45 | - --queues=realtime,celery 46 | - --schedule=/tmp/celerybeat-schedule 47 | 48 | ml_api: 49 | image: ghcr.io/gabe565/obico/ml-api 50 | environment: 51 | DEBUG: 'True' 52 | FLASK_APP: 'server.py' 53 | # ML_API_TOKEN: 54 | restart: unless-stopped 55 | tty: true 56 | command: [gunicorn, --bind=0.0.0.0:3333, --workers=1, --access-logfile=-, wsgi] 57 | 58 | redis: 59 | restart: unless-stopped 60 | image: redis:8.4-alpine 61 | 62 | volumes: 63 | static: {} 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Obico Docker Images 2 | 3 | [![Build](https://github.com/gabe565/docker-obico/actions/workflows/build.yml/badge.svg)](https://github.com/gabe565/docker-obico/actions/workflows/build.yml) 4 | 5 | This repo builds Docker images for [TheSpaghettiDetective/obico-server](https://github.com/TheSpaghettiDetective/obico-server) to be used in hosting environments that do not support building a local image. 6 | 7 | The Obico git ref is automatically updated by Renovate bot, so new Obico releases will be available within a few hours of a push to the Obico release branch. 8 | 9 | ## Images 10 | 11 | - [ghcr.io/gabe565/obico/web](https://github.com/gabe565/docker-obico/pkgs/container/obico%2Fweb) 12 | - [ghcr.io/gabe565/obico/ml-api](https://github.com/gabe565/docker-obico/pkgs/container/obico%2Fml-api) 13 | 14 | ## Deployment 15 | 16 | ### Docker 17 | 18 | These images are built very similarly to the [`docker-compose.yml`](https://github.com/TheSpaghettiDetective/obico-server/blob/release/docker-compose.yml) provided by Obico. 19 | 20 | The main difference is that the server container in this repo does not require a volume bind at `/frontend`. Those files are built directly into the container image. 21 | 22 | #### Usage 23 | 24 | 1. Copy [`.env.example`](.env.example) to `.env`. 25 | 2. Edit the file and set the desired values. 26 | 3. Run `docker compose up`. 27 | - If you want Obico to run in the background, add the `-d` flag. 28 | - Note that this step will take a while due to the size of the Obico images. 29 | 4. When ready, the web UI will be available at http://localhost:3334. 30 | - Default email: `root@example.com` 31 | - Default password: `password`. 32 | 5. Data will be stored in the `data` directory. 33 | 34 | ### Kubernetes 35 | 36 | I have built a Helm chart for Kubernetes deployments. See [charts.gabe565.com](https://charts.gabe565.com/charts/obico/) or [gabe565/charts](https://github.com/gabe565/charts/tree/main/charts/obico) for details. 37 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # Note: Please don't place single quotes (') or double quote (") around the values. Also it's case-sensitive 2 | 3 | # Generate your own unique secret key by running the following command: 4 | # docker compose exec web ./manage.py gen_site_secret 5 | DJANGO_SECRET_KEY= 6 | 7 | # Don't set DEBUG to True unless you know what you are doing. Otherwise, the static files will be cached in browser until hard-refresh 8 | DEBUG=False 9 | 10 | EMAIL_HOST= 11 | # Such as your email address for a Gmail account 12 | EMAIL_HOST_USER= 13 | # Your email account password 14 | EMAIL_HOST_PASSWORD= 15 | # Check with your email provider to make sure. 16 | EMAIL_PORT=587 17 | # Set it to False if your email provider doesn't use TLS, which is uncommon 18 | EMAIL_USE_TLS=True 19 | # The "FROM" email address in all emails sent by the system 20 | DEFAULT_FROM_EMAIL=changeme@example.com 21 | 22 | # set it to True if https is set up 23 | SITE_USES_HTTPS=False 24 | 25 | # set it to True if the site configured in django admin is accessible from the internet 26 | SITE_IS_PUBLIC=False 27 | 28 | # Set it to True to allow social account login. You will need to set "Provider" in Django admin (https://django-allauth.readthedocs.io/en/latest/providers.html) 29 | SOCIAL_LOGIN=False 30 | 31 | # Don't set it unless you know what you are doing. 32 | REDIS_URL=redis://redis:6379 33 | 34 | # Don't set it unless you know what you are doing. 35 | DATABASE_URL=sqlite:////data/db.sqlite3 36 | 37 | INTERNAL_MEDIA_HOST=http://web:3334 38 | ML_API_HOST=http://ml_api:3333 39 | 40 | # Set to True if you want to open sign up form 41 | ACCOUNT_ALLOW_SIGN_UP=False 42 | 43 | # Don't set it to True unless you want to develop the frontend 44 | WEBPACK_LOADER_ENABLED=False 45 | 46 | # IP whitelist for the /admin/ page. For example: ["1.2.3.4", "5.6.7.8"]. If not set, the whilelist will be disable and the /admin/ page will be open to all. 47 | ADMIN_IP_WHITELIST= 48 | 49 | # https://core.telegram.org/bots#6-botfather for how to create a telegram bot and get its token 50 | TELEGRAM_BOT_TOKEN= 51 | 52 | # https://django-twilio.readthedocs.io/en/latest/settings.html for how to find and set the TWILIO_XXX vars 53 | TWILIO_ACCOUNT_SID= 54 | TWILIO_AUTH_TOKEN= 55 | TWILIO_FROM_NUMBER= 56 | 57 | # https://docs.sentry.io/product/sentry-basics/dsn-explainer/ 58 | SENTRY_DSN= 59 | 60 | # https://pushover.net/api#registration for how to register an app api token 61 | PUSHOVER_APP_TOKEN= 62 | 63 | # https://api.slack.com/legacy/oauth 64 | SLACK_CLIENT_ID= 65 | SLACK_CLIENT_SECRET= 66 | 67 | OCTOPRINT_TUNNEL_PORT_RANGE=0-0 68 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: {} 5 | workflow_dispatch: {} 6 | 7 | env: 8 | OBICO_REPO: TheSpaghettiDetective/obico-server 9 | OBICO_BRANCH: release 10 | OBICO_REF: e3993e83d5a7f07617275c3e71b011c5ca59fa4d 11 | 12 | jobs: 13 | build-backend: 14 | name: Build Backend 15 | runs-on: ubuntu-latest 16 | permissions: 17 | contents: read 18 | packages: write 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 22 | with: 23 | repository: ${{ env.OBICO_REPO }} 24 | ref: ${{ env.OBICO_REF }} 25 | - name: Add frontend 26 | run: | 27 | mv frontend backend/ 28 | echo 'RUN ln -s /app/frontend /frontend' >> backend/Dockerfile 29 | - id: short-sha 30 | name: Get short sha 31 | run: echo "SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT 32 | - name: Docker meta 33 | id: meta 34 | uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 35 | with: 36 | images: | 37 | ghcr.io/gabe565/obico/web 38 | tags: | 39 | type=raw,priority=1000,value=latest 40 | type=raw,value=${{ env.OBICO_BRANCH }} 41 | type=raw,value=sha-${{ steps.short-sha.outputs.SHA }} 42 | type=raw,value=sha-${{ env.OBICO_REF }} 43 | labels: | 44 | org.opencontainers.image.title=Obico Web 45 | maintainer=gabe565 46 | org.opencontainers.image.vendor=gabe565 47 | org.opencontainers.image.description=Prebuilt Obico web container 48 | org.opencontainers.image.source=https://github.com/${{ env.OBICO_REPO }} 49 | org.opencontainers.image.revision=${{ env.OBICO_REF }} 50 | org.opencontainers.image.licenses=AGPL-3.0 51 | - name: Set up QEMU 52 | uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 53 | with: 54 | platforms: arm64 55 | - name: Set up Buildx 56 | uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 57 | - name: Login to GitHub Container Registry 58 | uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 59 | with: 60 | registry: ghcr.io 61 | username: ${{ github.actor }} 62 | password: ${{ github.token }} 63 | - name: Build and Push 64 | uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 65 | with: 66 | context: backend 67 | pull: true 68 | push: ${{ github.ref == 'refs/heads/main' }} 69 | platforms: linux/amd64,linux/arm64 70 | tags: ${{ steps.meta.outputs.tags }} 71 | labels: ${{ steps.meta.outputs.labels }} 72 | cache-from: type=gha 73 | cache-to: type=gha,mode=max 74 | 75 | build-ml-api: 76 | name: Build ML API 77 | runs-on: ubuntu-latest 78 | permissions: 79 | contents: read 80 | packages: write 81 | steps: 82 | - name: Checkout 83 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 84 | with: 85 | repository: ${{ env.OBICO_REPO }} 86 | ref: ${{ env.OBICO_REF }} 87 | - id: short-sha 88 | name: Get short sha 89 | run: echo "SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT 90 | - name: Docker meta 91 | id: meta 92 | uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 93 | with: 94 | images: | 95 | ghcr.io/gabe565/obico/ml-api 96 | tags: | 97 | type=raw,priority=1000,value=latest 98 | type=raw,value=${{ env.OBICO_BRANCH }} 99 | type=raw,value=sha-${{ steps.short-sha.outputs.SHA }} 100 | type=raw,value=sha-${{ env.OBICO_REF }} 101 | labels: | 102 | org.opencontainers.image.title=Obico ML API 103 | maintainer=gabe565 104 | org.opencontainers.image.vendor=gabe565 105 | org.opencontainers.image.description=Prebuilt Obico ML API container 106 | org.opencontainers.image.source=https://github.com/${{ env.OBICO_REPO }} 107 | org.opencontainers.image.revision=${{ env.OBICO_REF }} 108 | org.opencontainers.image.licenses=AGPL-3.0 109 | - name: Set up QEMU 110 | uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 111 | with: 112 | platforms: arm64 113 | - name: Set up Buildx 114 | uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 115 | - name: Login to GitHub Container Registry 116 | uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 117 | with: 118 | registry: ghcr.io 119 | username: ${{ github.actor }} 120 | password: ${{ github.token }} 121 | - name: Build and Push 122 | uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 123 | with: 124 | context: ml_api 125 | pull: true 126 | push: ${{ github.ref == 'refs/heads/main' }} 127 | platforms: linux/amd64,linux/arm64 128 | tags: ${{ steps.meta.outputs.tags }} 129 | labels: ${{ steps.meta.outputs.labels }} 130 | cache-from: type=gha 131 | cache-to: type=gha,mode=max 132 | --------------------------------------------------------------------------------