mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-18 20:59:41 +02:00
feat: consolidate deployment targets and publish to ghcr.io (#2539)
* WIP: proof of concept * basic meta tag injection * add support for scraping public/private links * make tests go brrrrr * cleanup initialization * rewrite build config * remove recipe meta on frontend * make type checker happy * remove other deployment methods * fix issue with JSON response on un-authenticated request * docs updates * update tivy scanner * fix linter stuff * change registry tag * build fixes * fix same mistake I always make
This commit is contained in:
parent
aec4cb4f31
commit
2ad6af2cce
34 changed files with 268 additions and 793 deletions
|
@ -12,14 +12,7 @@ RUN yarn install \
|
|||
# https://github.com/docker/build-push-action/issues/471
|
||||
--network-timeout 1000000
|
||||
|
||||
RUN yarn build
|
||||
|
||||
RUN rm -rf node_modules && \
|
||||
NODE_ENV=production yarn install \
|
||||
--prefer-offline \
|
||||
--pure-lockfile \
|
||||
--non-interactive \
|
||||
--production=true
|
||||
RUN yarn generate
|
||||
|
||||
###############################################
|
||||
# Base Image - Python
|
||||
|
@ -150,12 +143,13 @@ HEALTHCHECK CMD python $MEALIE_HOME/mealie/scripts/healthcheck.py || exit 1
|
|||
# Copy Frontend
|
||||
|
||||
# copying caddy into image
|
||||
COPY --from=builder /app $MEALIE_HOME/frontend/
|
||||
ENV STATIC_FILES=/spa/static
|
||||
COPY --from=builder /app/dist ${STATIC_FILES}
|
||||
|
||||
ENV HOST 0.0.0.0
|
||||
|
||||
EXPOSE ${APP_PORT}
|
||||
COPY ./docker/omni.entry.sh $MEALIE_HOME/run.sh
|
||||
COPY ./docker/entry.sh $MEALIE_HOME/run.sh
|
||||
|
||||
RUN chmod +x $MEALIE_HOME/run.sh
|
||||
ENTRYPOINT $MEALIE_HOME/run.sh
|
|
@ -1,115 +0,0 @@
|
|||
###############################################
|
||||
# Base Image
|
||||
###############################################
|
||||
FROM python:3.10-slim as python-base
|
||||
|
||||
ENV MEALIE_HOME="/app"
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
PIP_NO_CACHE_DIR=off \
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=on \
|
||||
PIP_DEFAULT_TIMEOUT=100 \
|
||||
POETRY_HOME="/opt/poetry" \
|
||||
POETRY_VIRTUALENVS_IN_PROJECT=true \
|
||||
POETRY_NO_INTERACTION=1 \
|
||||
PYSETUP_PATH="/opt/pysetup" \
|
||||
VENV_PATH="/opt/pysetup/.venv"
|
||||
|
||||
# prepend poetry and venv to path
|
||||
ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"
|
||||
|
||||
# create user account
|
||||
RUN useradd -u 911 -U -d $MEALIE_HOME -s /bin/bash abc \
|
||||
&& usermod -G users abc \
|
||||
&& mkdir $MEALIE_HOME
|
||||
|
||||
###############################################
|
||||
# Builder Image
|
||||
###############################################
|
||||
FROM python-base as builder-base
|
||||
RUN apt-get update \
|
||||
&& apt-get install --no-install-recommends -y \
|
||||
curl \
|
||||
build-essential \
|
||||
libpq-dev \
|
||||
libwebp-dev \
|
||||
tesseract-ocr-all \
|
||||
# LDAP Dependencies
|
||||
libsasl2-dev libldap2-dev libssl-dev \
|
||||
gnupg gnupg2 gnupg1 \
|
||||
&& pip install -U --no-cache-dir pip
|
||||
|
||||
# install poetry - respects $POETRY_VERSION & $POETRY_HOME
|
||||
ENV POETRY_VERSION=1.3.1
|
||||
RUN curl -sSL https://install.python-poetry.org | python3 -
|
||||
|
||||
# copy project requirement files here to ensure they will be cached.
|
||||
WORKDIR $PYSETUP_PATH
|
||||
COPY ./poetry.lock ./pyproject.toml ./
|
||||
|
||||
# install runtime deps - uses $POETRY_VIRTUALENVS_IN_PROJECT internally
|
||||
RUN poetry install -E pgsql --only main
|
||||
|
||||
###############################################
|
||||
# CRFPP Image
|
||||
###############################################
|
||||
FROM hkotel/crfpp as crfpp
|
||||
|
||||
RUN echo "crfpp-container"
|
||||
|
||||
###############################################
|
||||
# Production Image
|
||||
###############################################
|
||||
FROM python-base as production
|
||||
ENV PRODUCTION=true
|
||||
ENV TESTING=false
|
||||
|
||||
ARG COMMIT
|
||||
ENV GIT_COMMIT_HASH=$COMMIT
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install --no-install-recommends -y \
|
||||
gosu \
|
||||
iproute2 \
|
||||
tesseract-ocr-all \
|
||||
libldap-common \
|
||||
&& apt-get autoremove \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# copying poetry and venv into image
|
||||
COPY --from=builder-base $POETRY_HOME $POETRY_HOME
|
||||
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
|
||||
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib
|
||||
COPY --from=crfpp /usr/local/lib/ /usr/local/lib
|
||||
COPY --from=crfpp /usr/local/bin/crf_learn /usr/local/bin/crf_learn
|
||||
COPY --from=crfpp /usr/local/bin/crf_test /usr/local/bin/crf_test
|
||||
|
||||
# copy backend
|
||||
COPY ./mealie $MEALIE_HOME/mealie
|
||||
COPY ./poetry.lock ./pyproject.toml $MEALIE_HOME/
|
||||
COPY ./gunicorn_conf.py $MEALIE_HOME
|
||||
|
||||
# Alembic
|
||||
COPY ./alembic $MEALIE_HOME/alembic
|
||||
COPY ./alembic.ini $MEALIE_HOME/
|
||||
|
||||
# venv already has runtime deps installed we get a quicker install
|
||||
WORKDIR $MEALIE_HOME
|
||||
RUN . $VENV_PATH/bin/activate && poetry install -E pgsql --only main
|
||||
WORKDIR /
|
||||
|
||||
# Grab CRF++ Model Release
|
||||
RUN python $MEALIE_HOME/mealie/scripts/install_model.py
|
||||
|
||||
VOLUME [ "$MEALIE_HOME/data/" ]
|
||||
ENV APP_PORT=9000
|
||||
|
||||
EXPOSE ${APP_PORT}
|
||||
|
||||
HEALTHCHECK CMD python $MEALIE_HOME/mealie/scripts/healthcheck.py || exit 1
|
||||
|
||||
COPY ./docker/api.entry.sh $MEALIE_HOME/mealie/run.sh
|
||||
RUN chmod +x $MEALIE_HOME/mealie/run.sh
|
||||
ENTRYPOINT $MEALIE_HOME/mealie/run.sh
|
|
@ -1,58 +1,20 @@
|
|||
version: "3.4"
|
||||
services:
|
||||
mealie-frontend:
|
||||
container_name: mealie-frontend
|
||||
image: mealie-frontend:dev
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 500M
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: ./docker/frontend.Dockerfile
|
||||
restart: always
|
||||
volumes:
|
||||
- mealie-data:/app/data/
|
||||
ports:
|
||||
- 9091:3000
|
||||
environment:
|
||||
- API_URL=http://mealie-api:9000
|
||||
|
||||
# =====================================
|
||||
# Light Mode Config
|
||||
- THEME_LIGHT_PRIMARY=#E58325
|
||||
- THEME_LIGHT_ACCENT=#007A99
|
||||
- THEME_LIGHT_SECONDARY=#973542
|
||||
- THEME_LIGHT_SUCCESS=#43A047
|
||||
- THEME_LIGHT_INFO=#1976D2
|
||||
- THEME_LIGHT_WARNING=#FF6D00
|
||||
- THEME_LIGHT_ERROR=#EF5350
|
||||
# =====================================
|
||||
# Dark Mode Config
|
||||
- THEME_DARK_PRIMARY=#E58325
|
||||
- THEME_DARK_ACCENT=#007A99
|
||||
- THEME_DARK_SECONDARY=#973542
|
||||
- THEME_DARK_SUCCESS=#43A047
|
||||
- THEME_DARK_INFO=#1976D2
|
||||
- THEME_DARK_WARNING=#FF6D00
|
||||
- THEME_DARK_ERROR=#EF5350
|
||||
mealie:
|
||||
container_name: mealie-api
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1000M
|
||||
container_name: mealie
|
||||
image: mealie:dev
|
||||
build:
|
||||
context: ../
|
||||
target: production
|
||||
dockerfile: ./docker/api.Dockerfile
|
||||
dockerfile: ./docker/Dockerfile
|
||||
restart: always
|
||||
volumes:
|
||||
- mealie-data:/app/data/
|
||||
ports:
|
||||
- 9092:9000
|
||||
- 9091:9000
|
||||
environment:
|
||||
ALLOW_SIGNUP: "false"
|
||||
|
||||
DB_ENGINE: sqlite # Optional: 'sqlite', 'postgres'
|
||||
# =====================================
|
||||
# Postgres Config
|
||||
|
@ -78,14 +40,6 @@ services:
|
|||
# SMTP_USER=
|
||||
# SMTP_PASSWORD=
|
||||
|
||||
# postgres:
|
||||
# container_name: postgres
|
||||
# image: postgres
|
||||
# restart: always
|
||||
# environment:
|
||||
# POSTGRES_PASSWORD: mealie
|
||||
# POSTGRES_USER: mealie
|
||||
|
||||
volumes:
|
||||
mealie-data:
|
||||
driver: local
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# Start Backend API
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Get Reload Arg `run.sh reload` for dev server
|
||||
ARG1=${1:-production}
|
||||
# Strict Mode
|
||||
# set -e
|
||||
# IFS=$'\n\t'
|
||||
|
||||
# Get PUID/PGID
|
||||
PUID=${PUID:-911}
|
||||
|
@ -41,12 +41,8 @@ init() {
|
|||
poetry run python /app/mealie/db/init_db.py
|
||||
}
|
||||
|
||||
echo "Production"
|
||||
|
||||
change_user
|
||||
|
||||
# change_user
|
||||
init
|
||||
|
||||
GUNICORN_PORT=${API_PORT:-9000}
|
||||
|
||||
# Start API
|
|
@ -1,46 +0,0 @@
|
|||
{
|
||||
auto_https off
|
||||
admin off
|
||||
}
|
||||
|
||||
:3000 {
|
||||
@apidocs path /docs /openapi.json
|
||||
|
||||
@static {
|
||||
file
|
||||
path *.ico *.css *.js *.gif *.jpg *.jpeg *.png *.svg *.woff *.woff2 *.webp
|
||||
}
|
||||
|
||||
encode gzip zstd
|
||||
|
||||
# Handles Recipe Images / Assets
|
||||
handle_path /api/media/recipes/* {
|
||||
header @static Cache-Control max-age=31536000
|
||||
root * /app/data/recipes/
|
||||
file_server
|
||||
}
|
||||
|
||||
# Handles User Images
|
||||
handle_path /api/media/users/* {
|
||||
header @static Cache-Control max-age=31536000
|
||||
root * /app/data/users/
|
||||
file_server
|
||||
}
|
||||
|
||||
# Handle Docker Volume Validation File
|
||||
handle_path /api/media/docker/* {
|
||||
root * /app/data/docker-validation/
|
||||
file_server
|
||||
}
|
||||
|
||||
|
||||
handle @apidocs {
|
||||
uri strip_suffix /
|
||||
reverse_proxy {$API_URL}
|
||||
}
|
||||
|
||||
handle {
|
||||
uri strip_suffix /
|
||||
reverse_proxy http://127.0.0.1:3001
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
FROM node:16 as builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY ./frontend .
|
||||
|
||||
RUN yarn install \
|
||||
--prefer-offline \
|
||||
--frozen-lockfile \
|
||||
--non-interactive \
|
||||
--production=false \
|
||||
# https://github.com/docker/build-push-action/issues/471
|
||||
--network-timeout 1000000
|
||||
|
||||
RUN yarn build
|
||||
|
||||
RUN rm -rf node_modules && \
|
||||
NODE_ENV=production yarn install \
|
||||
--prefer-offline \
|
||||
--pure-lockfile \
|
||||
--non-interactive \
|
||||
--production=true
|
||||
|
||||
FROM node:16-alpine
|
||||
|
||||
RUN apk add caddy
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# copying caddy into image
|
||||
COPY --from=builder /app .
|
||||
COPY ./docker/frontend.Caddyfile /app/Caddyfile
|
||||
COPY ./docker/frontend.entry.sh /app/run.sh
|
||||
|
||||
ENV HOST 0.0.0.0
|
||||
EXPOSE 3000
|
||||
|
||||
RUN chmod +x /app/run.sh
|
||||
ENTRYPOINT /app/run.sh
|
|
@ -1,7 +0,0 @@
|
|||
# Production entry point for the frontend docker container
|
||||
|
||||
# Web Server
|
||||
caddy start --config /app/Caddyfile
|
||||
|
||||
# Start Node Application
|
||||
yarn start -p 3001
|
|
@ -1,45 +0,0 @@
|
|||
version: "3.4"
|
||||
services:
|
||||
omni-mealie:
|
||||
container_name: mealie
|
||||
image: mealie-omni:dev
|
||||
build:
|
||||
context: ../
|
||||
target: production
|
||||
dockerfile: ./docker/omni.Dockerfile
|
||||
restart: always
|
||||
volumes:
|
||||
- mealie-data:/app/data/
|
||||
ports:
|
||||
- 9091:3000
|
||||
environment:
|
||||
ALLOW_SIGNUP: "false"
|
||||
|
||||
DB_ENGINE: sqlite # Optional: 'sqlite', 'postgres'
|
||||
# =====================================
|
||||
# Postgres Config
|
||||
POSTGRES_USER: mealie
|
||||
POSTGRES_PASSWORD: mealie
|
||||
POSTGRES_SERVER: postgres
|
||||
POSTGRES_PORT: 5432
|
||||
POSTGRES_DB: mealie
|
||||
|
||||
# =====================================
|
||||
# Web Concurrency
|
||||
WEB_GUNICORN: "false"
|
||||
WORKERS_PER_CORE: 0.5
|
||||
MAX_WORKERS: 1
|
||||
WEB_CONCURRENCY: 1
|
||||
# =====================================
|
||||
# Email Configuration
|
||||
# SMTP_HOST=
|
||||
# SMTP_PORT=587
|
||||
# SMTP_FROM_NAME=Mealie
|
||||
# SMTP_AUTH_STRATEGY=TLS # Options: 'TLS', 'SSL', 'NONE'
|
||||
# SMTP_FROM_EMAIL=
|
||||
# SMTP_USER=
|
||||
# SMTP_PASSWORD=
|
||||
|
||||
volumes:
|
||||
mealie-data:
|
||||
driver: local
|
|
@ -1,59 +0,0 @@
|
|||
# Start Backend API
|
||||
#!/bin/bash
|
||||
|
||||
# Strict Mode
|
||||
# set -e
|
||||
# IFS=$'\n\t'
|
||||
|
||||
# Get PUID/PGID
|
||||
PUID=${PUID:-911}
|
||||
PGID=${PGID:-911}
|
||||
|
||||
add_user() {
|
||||
groupmod -o -g "$PGID" abc
|
||||
usermod -o -u "$PUID" abc
|
||||
}
|
||||
|
||||
change_user() {
|
||||
# If container is started as root then create a new user and switch to it
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
add_user
|
||||
chown -R $PUID:$PGID /app
|
||||
|
||||
echo "Switching to dedicated user"
|
||||
exec gosu $PUID "$BASH_SOURCE" "$@"
|
||||
elif [ "$(id -u)" = $PUID ]; then
|
||||
echo "
|
||||
User uid: $PUID
|
||||
User gid: $PGID
|
||||
"
|
||||
fi
|
||||
}
|
||||
|
||||
init() {
|
||||
# $MEALIE_HOME directory
|
||||
cd /app
|
||||
|
||||
# Activate our virtual environment here
|
||||
. /opt/pysetup/.venv/bin/activate
|
||||
|
||||
# Initialize Database Prerun
|
||||
poetry run python /app/mealie/db/init_db.py
|
||||
}
|
||||
|
||||
# change_user
|
||||
init
|
||||
GUNICORN_PORT=${API_PORT:-9000}
|
||||
|
||||
# Start API
|
||||
hostip=`/sbin/ip route|awk '/default/ { print $3 }'`
|
||||
if [ "$WEB_GUNICORN" = 'true' ]; then
|
||||
echo "Starting Gunicorn"
|
||||
gunicorn mealie.app:app -b 0.0.0.0:$GUNICORN_PORT --forwarded-allow-ips=$hostip -k uvicorn.workers.UvicornWorker -c /app/gunicorn_conf.py --preload &
|
||||
else
|
||||
uvicorn mealie.app:app --host 0.0.0.0 --forwarded-allow-ips=$hostip --port $GUNICORN_PORT &
|
||||
fi
|
||||
|
||||
# ------------------------------
|
||||
# Start Frontend Nuxt Server
|
||||
cd /app/frontend && yarn start -p 3000
|
Loading…
Add table
Add a link
Reference in a new issue