Refactor docker image for devcontainer (#6029)

* Make base image configurable

* Refactor dockerfile

- Place extra packages into extra shell script
- Add pre-build stage where packages are installed, and then cache removed
- Run same script in dev target, but do not remove

* Run docker workflow whenever package requirements change

* Replace devcontainer dockerfile

* Install base packages in devcontainer

* --no-cache-dir
This commit is contained in:
Oliver 2023-12-05 07:05:48 +11:00 committed by GitHub
parent 15f58b965e
commit f96055a33f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 80 deletions

View File

@ -1,52 +0,0 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.241.1/containers/python-3/.devcontainer/base.Dockerfile
# [Choice] Python version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.10, 3.9, 3.8, 3.7, 3.6, 3-bullseye, 3.10-bullseye, 3.9-bullseye, 3.8-bullseye, 3.7-bullseye, 3.6-bullseye, 3-buster, 3.10-buster, 3.9-buster, 3.8-buster, 3.7-buster, 3.6-buster
ARG VARIANT="3.10-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
ARG WORKSPACE="/workspaces/InvenTree"
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
ARG NODE_VERSION="18"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
# [Optional] If your pip requirements rarely change, uncomment this section to add them to the image.
# COPY requirements.txt /tmp/pip-tmp/
# RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
# && rm -rf /tmp/pip-tmp
# [Optional] Uncomment this section to install additional OS packages.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive && \
apt-get -y install --no-install-recommends \
git gcc g++ gettext gnupg2 libffi-dev \
# Weasyprint requirements : https://doc.courtbouillon.org/weasyprint/stable/first_steps.html#debian-11
poppler-utils libpango-1.0-0 libpangoft2-1.0-0 \
# Image format support
libjpeg-dev webp \
# SQLite support
sqlite3 \
# PostgreSQL support
libpq-dev \
# MySQL / MariaDB support
default-libmysqlclient-dev mariadb-client \
# LDAP support
libldap2-dev libsasl2-dev && \
apt-get autoclean && apt-get autoremove && \
rm -rf /var/lib/apt/lists/*
# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
# Update pip
RUN pip install --no-cache-dir --upgrade pip
# Install required base-level python packages
COPY ./docker/requirements.txt base_requirements.txt
RUN pip install --disable-pip-version-check --no-cache-dir -U -r base_requirements.txt
# preserve command history between container starts
# Ref: https://code.visualstudio.com/remote/advancedcontainers/persist-bash-history
# Folder will be created in 'postCreateCommand' in devcontainer.json as it's not preserved due to the bind mount
RUN echo "export PROMPT_COMMAND='history -a' && export HISTFILE=${WORKSPACE}/dev/commandhistory/.bash_history" >> "/home/vscode/.bashrc"
WORKDIR ${WORKSPACE}

View File

@ -3,16 +3,12 @@
{ {
"name": "InvenTree", "name": "InvenTree",
"build": { "build": {
"dockerfile": "Dockerfile", "dockerfile": "../Dockerfile",
"context": "..", "context": "..",
"target": "devcontainer",
"args": { "args": {
// Update 'VARIANT' to pick a Python version: 3, 3.10, 3.9, 3.8, 3.7, 3.6 "base_image": "mcr.microsoft.com/vscode/devcontainers/base:alpine-3.18",
// Append -bullseye or -buster to pin to an OS version. "workspace": "${containerWorkspaceFolder}"
// Use -bullseye variants on local on arm64/Apple Silicon.
"VARIANT": "3.10-bullseye",
// Options
"NODE_VERSION": "lts/*",
"WORKSPACE": "${containerWorkspaceFolder}"
} }
}, },
@ -48,8 +44,11 @@
}, },
// Use 'forwardPorts' to make a list of ports inside the container available locally. // Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [8000], "forwardPorts": [5173, 8000],
"portsAttributes": { "portsAttributes": {
"5173": {
"label": "Vite server"
},
"8000": { "8000": {
"label": "InvenTree server" "label": "InvenTree server"
} }
@ -60,9 +59,9 @@
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode", "remoteUser": "vscode",
"containerUser": "vscode",
"features": { "features": {
"git": "os-provided", "git": "os-provided"
"github-cli": "latest"
}, },
"remoteEnv": { "remoteEnv": {

View File

@ -9,12 +9,12 @@ mkdir -p $1/dev/{commandhistory,plugins}
cd $1 cd $1
# create venv # create venv
python3 -m venv dev/venv python3 -m venv $1/dev/venv
. dev/venv/bin/activate . $1/dev/venv/bin/activate
# setup InvenTree server # setup InvenTree server
pip install invoke pip install invoke
invoke update --no-frontend invoke update
invoke setup-dev invoke setup-dev
invoke frontend-install invoke frontend-install

View File

@ -45,6 +45,7 @@ jobs:
- docker-compose.yml - docker-compose.yml
- docker.dev.env - docker.dev.env
- Dockerfile - Dockerfile
- requirements.txt
# Build the docker image # Build the docker image

View File

@ -9,7 +9,8 @@
# - Runs InvenTree web server under django development server # - Runs InvenTree web server under django development server
# - Monitors source files for any changes, and live-reloads server # - Monitors source files for any changes, and live-reloads server
FROM python:3.10-alpine3.18 as inventree_base ARG base_image=python:3.10-alpine3.18
FROM ${base_image} as inventree_base
# Build arguments for this image # Build arguments for this image
ARG commit_hash="" ARG commit_hash=""
@ -53,6 +54,7 @@ LABEL org.label-schema.schema-version="1.0" \
org.label-schema.vcs-url="https://github.com/inventree/InvenTree.git" \ org.label-schema.vcs-url="https://github.com/inventree/InvenTree.git" \
org.label-schema.vcs-ref=${commit_tag} org.label-schema.vcs-ref=${commit_tag}
# Install required system level packages
RUN apk add --no-cache \ RUN apk add --no-cache \
git gettext py-cryptography \ git gettext py-cryptography \
# Image format support # Image format support
@ -75,6 +77,8 @@ WORKDIR ${INVENTREE_HOME}
COPY ./docker/requirements.txt base_requirements.txt COPY ./docker/requirements.txt base_requirements.txt
COPY ./requirements.txt ./ COPY ./requirements.txt ./
COPY ./docker/install_build_packages.sh .
RUN chmod +x install_build_packages.sh
# For ARMv7 architecture, add the piwheels repo (for cryptography library) # For ARMv7 architecture, add the piwheels repo (for cryptography library)
# Otherwise, we have to build from source, which is difficult # Otherwise, we have to build from source, which is difficult
@ -83,23 +87,19 @@ RUN if [ `apk --print-arch` = "armv7" ]; then \
printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf ; \ printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf ; \
fi fi
RUN apk add --no-cache --virtual .build-deps \
gcc g++ musl-dev openssl-dev libffi-dev cargo python3-dev openldap-dev \
# Image format dev libs
jpeg-dev openjpeg-dev libwebp-dev zlib-dev \
# DB specific dev libs
postgresql-dev sqlite-dev mariadb-dev && \
pip install -r base_requirements.txt -r requirements.txt --no-cache-dir && \
apk --purge del .build-deps
COPY tasks.py docker/gunicorn.conf.py docker/init.sh ./ COPY tasks.py docker/gunicorn.conf.py docker/init.sh ./
RUN chmod +x init.sh RUN chmod +x init.sh
ENTRYPOINT ["/bin/sh", "./init.sh"] ENTRYPOINT ["/bin/sh", "./init.sh"]
FROM inventree_base as prebuild
RUN ./install_build_packages.sh --no-cache --virtual .build-deps && \
pip install -r base_requirements.txt -r requirements.txt --no-cache-dir && \
apk --purge del .build-deps
# Frontend builder image: # Frontend builder image:
FROM inventree_base as frontend FROM prebuild as frontend
RUN apk add --no-cache --update nodejs npm && npm install -g yarn RUN apk add --no-cache --update nodejs npm && npm install -g yarn
RUN yarn config set network-timeout 600000 -g RUN yarn config set network-timeout 600000 -g
@ -111,7 +111,7 @@ RUN cd ${INVENTREE_HOME}/InvenTree && inv frontend-compile
# InvenTree production image: # InvenTree production image:
# - Copies required files from local directory # - Copies required files from local directory
# - Starts a gunicorn webserver # - Starts a gunicorn webserver
FROM inventree_base as production FROM prebuild as production
ENV INVENTREE_DEBUG=False ENV INVENTREE_DEBUG=False
@ -128,9 +128,16 @@ COPY --from=frontend ${INVENTREE_HOME}/InvenTree/web/static/web ./InvenTree/web/
# TODO: e.g. -b ${INVENTREE_WEB_ADDR}:${INVENTREE_WEB_PORT} fails here # TODO: e.g. -b ${INVENTREE_WEB_ADDR}:${INVENTREE_WEB_PORT} fails here
CMD gunicorn -c ./gunicorn.conf.py InvenTree.wsgi -b 0.0.0.0:8000 --chdir ./InvenTree CMD gunicorn -c ./gunicorn.conf.py InvenTree.wsgi -b 0.0.0.0:8000 --chdir ./InvenTree
FROM inventree_base as dev FROM inventree_base as dev
# Vite server (for local frontend development)
EXPOSE 5173
# Install packages required for building python packages
RUN ./install_build_packages.sh
RUN pip install -r base_requirements.txt --no-cache-dir
# Install nodejs / npm / yarn # Install nodejs / npm / yarn
RUN apk add --no-cache --update nodejs npm && npm install -g yarn RUN apk add --no-cache --update nodejs npm && npm install -g yarn
@ -152,3 +159,10 @@ ENTRYPOINT ["/bin/ash", "./docker/init.sh"]
# Launch the development server # Launch the development server
CMD ["invoke", "server", "-a", "${INVENTREE_WEB_ADDR}:${INVENTREE_WEB_PORT}"] CMD ["invoke", "server", "-a", "${INVENTREE_WEB_ADDR}:${INVENTREE_WEB_PORT}"]
# Image target for devcontainer
FROM dev as devcontainer
ARG workspace="/workspaces/InvenTree"
WORKDIR ${WORKSPACE}

View File

@ -0,0 +1,8 @@
#!/bin/ash
# Install system packages required for building InvenTree python libraries
apk add gcc g++ musl-dev openssl-dev libffi-dev cargo python3-dev openldap-dev \
jpeg-dev openjpeg-dev libwebp-dev zlib-dev \
postgresql-dev sqlite-dev mariadb-dev \
$@