Add Alpine based Docker image (experimental) (#570)

* use alpine as base image

* try fix missing mime types

* Extract separate Dockerfile

* Restore playwright dev dependency

* Add info to README.md
This commit is contained in:
Sascha Ißbrücker 2023-11-05 14:18:26 +01:00 committed by GitHub
parent a130daa0f0
commit 87020de917
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 145 additions and 37 deletions

View file

@ -1,34 +1,22 @@
# Remove project files, data, tmp files, build files # Ignore everything
/.env *
/.idea
/data
/node_modules
/tmp
/docs
/static
/scripts
/build
/out
/.git
/.devcontainer
/.dockerignore # Include files required for build or at runtime
/.gitignore !/bookmarks
/.gitattributes !/siteroot
/Dockerfile
/docker-compose.yml
/*.sh
/*.iml
/*.patch
/*.md
/*.js
/*.log
/*.pid
# Whitelist files needed in build or prod image
!/rollup.config.js
!/bootstrap.sh
!/background-tasks-wrapper.sh !/background-tasks-wrapper.sh
!/bootstrap.sh
!/LICENSE.txt
!/manage.py
!/package.json
!/package-lock.json
!/requirements.prod.txt
!/requirements.txt
!/rollup.config.js
!/supervisord.conf
!/uwsgi.ini
!/version.txt
# Remove development settings # Remove dev settings
/siteroot/settings/dev.py /siteroot/settings/dev.py

View file

@ -58,9 +58,27 @@ The name comes from:
linkding is designed to be run with container solutions like [Docker](https://docs.docker.com/get-started/). linkding is designed to be run with container solutions like [Docker](https://docs.docker.com/get-started/).
The Docker image is compatible with ARM platforms, so it can be run on a Raspberry Pi. The Docker image is compatible with ARM platforms, so it can be run on a Raspberry Pi.
By default, linkding uses SQLite as a database. linkding uses an SQLite database by default.
Alternatively linkding supports PostgreSQL, see the [database options](docs/Options.md#LD_DB_ENGINE) for more information. Alternatively linkding supports PostgreSQL, see the [database options](docs/Options.md#LD_DB_ENGINE) for more information.
<details>
<summary>🧪 Alpine-based image</summary>
The default Docker image (`latest` tag) is based on a slim variant of Debian Linux.
Alternatively, there is an image based on Alpine Linux (`latest-alpine` tag) which has a smaller size, resulting in a smaller download and less disk space required.
The Alpine image is currently about 45 MB in compressed size, compared to about 130 MB for the Debian image.
To use it, replace the `latest` tag with `latest-alpine`, either in the CLI command below when using Docker, or in the `docker-compose.yml` file when using docker-compose.
> [!WARNING]
> The image is currently considered experimental in order to gather feedback and iron out any issues.
> Only use it if you are comfortable running experimental software or want to help out with testing.
> While there should be no issues with creating new installations, there might be issues when migrating existing installations.
> If you plan to migrate your existing installation, make sure to create proper [backups](https://github.com/sissbruecker/linkding/blob/master/docs/backup.md) first.
</details>
### Using Docker ### Using Docker
To install linkding using Docker you can just run the [latest image](https://hub.docker.com/repository/docker/sissbruecker/linkding) from Docker Hub: To install linkding using Docker you can just run the [latest image](https://hub.docker.com/repository/docker/sissbruecker/linkding) from Docker Hub:

89
docker/alpine.Dockerfile Normal file
View file

@ -0,0 +1,89 @@
FROM node:18.18.0-alpine AS node-build
WORKDIR /etc/linkding
# install build dependencies
COPY rollup.config.js package.json package-lock.json ./
RUN npm install
# copy files needed for JS build
COPY bookmarks/frontend ./bookmarks/frontend
# run build
RUN npm run build
FROM python:3.10.13-alpine3.18 AS python-base
RUN apk update && apk add alpine-sdk linux-headers libpq-dev pkgconfig icu-dev sqlite-dev
WORKDIR /etc/linkding
FROM python-base AS python-build
# install build dependencies
COPY requirements.txt requirements.txt
# remove playwright from requirements as there is not always a distro and it's not needed for the build
RUN sed -i '/playwright/d' requirements.txt
RUN pip install -U pip && pip install -Ur requirements.txt
# copy files needed for Django build
COPY . .
COPY --from=node-build /etc/linkding .
# run Django part of the build
RUN python manage.py compilescss && \
python manage.py collectstatic --ignore=*.scss && \
python manage.py compilescss --delete-files
FROM python-base AS prod-deps
COPY requirements.prod.txt ./requirements.txt
RUN mkdir /opt/venv && \
python -m venv --upgrade-deps --copies /opt/venv && \
/opt/venv/bin/pip install --upgrade pip wheel && \
/opt/venv/bin/pip install -Ur requirements.txt
FROM python-base AS compile-icu
# Defines SQLite version
# Since this is only needed for downloading the header files this probably
# doesn't need to be up-to-date, assuming the SQLite APIs used by the ICU
# extension do not change
ARG SQLITE_RELEASE_YEAR=2023
ARG SQLITE_RELEASE=3430000
# Compile the ICU extension needed for case-insensitive search and ordering
# with SQLite. This does:
# - Download SQLite amalgamation for header files
# - Download ICU extension source file
# - Compile ICU extension
RUN wget https://www.sqlite.org/${SQLITE_RELEASE_YEAR}/sqlite-amalgamation-${SQLITE_RELEASE}.zip && \
unzip sqlite-amalgamation-${SQLITE_RELEASE}.zip && \
cp sqlite-amalgamation-${SQLITE_RELEASE}/sqlite3.h ./sqlite3.h && \
cp sqlite-amalgamation-${SQLITE_RELEASE}/sqlite3ext.h ./sqlite3ext.h && \
wget https://www.sqlite.org/src/raw/ext/icu/icu.c?name=91c021c7e3e8bbba286960810fa303295c622e323567b2e6def4ce58e4466e60 -O icu.c && \
gcc -fPIC -shared icu.c `pkg-config --libs --cflags icu-uc icu-io` -o libicu.so
FROM python:3.10.13-alpine3.18 AS final
# install runtime dependencies
RUN apk update && apk add bash curl icu libpq mailcap
# create www-data user and group
RUN set -x ; \
addgroup -g 82 -S www-data ; \
adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1
WORKDIR /etc/linkding
# copy prod dependencies
COPY --from=prod-deps /opt/venv /opt/venv
# copy output from build stage
COPY --from=python-build /etc/linkding/static static/
# copy compiled icu extension
COPY --from=compile-icu /etc/linkding/libicu.so libicu.so
# copy application code
COPY . .
# Expose uwsgi server at port 9090
EXPOSE 9090
# Activate virtual env
ENV VIRTUAL_ENV /opt/venv
ENV PATH /opt/venv/bin:$PATH
# Allow running containers as an an arbitrary user in the root group, to support deployment scenarios like OpenShift, Podman
RUN chmod g+w . && \
chmod +x ./bootstrap.sh
HEALTHCHECK --interval=30s --retries=3 --timeout=1s \
CMD curl -f http://localhost:${LD_SERVER_PORT:-9090}/${LD_CONTEXT_PATH}health || exit 1
CMD ["./bootstrap.sh"]

View file

@ -1,11 +1,11 @@
FROM node:18.18.0-alpine AS node-build FROM node:18.18.0-alpine AS node-build
WORKDIR /etc/linkding WORKDIR /etc/linkding
# install build dependencies # install build dependencies
COPY package.json package-lock.json ./ COPY rollup.config.js package.json package-lock.json ./
RUN npm install -g npm && \ RUN npm install
npm install # copy files needed for JS build
# compile JS components COPY bookmarks/frontend ./bookmarks/frontend
COPY . . # run build
RUN npm run build RUN npm run build
@ -17,9 +17,13 @@ WORKDIR /etc/linkding
FROM python-base AS python-build FROM python-base AS python-build
# install build dependencies # install build dependencies
COPY requirements.txt requirements.txt COPY requirements.txt requirements.txt
# remove playwright from requirements as there is not always a distro and it's not needed for the build
RUN sed -i '/playwright/d' requirements.txt
RUN pip install -U pip && pip install -Ur requirements.txt RUN pip install -U pip && pip install -Ur requirements.txt
# run Django part of the build # copy files needed for Django build
COPY . .
COPY --from=node-build /etc/linkding . COPY --from=node-build /etc/linkding .
# run Django part of the build
RUN python manage.py compilescss && \ RUN python manage.py compilescss && \
python manage.py collectstatic --ignore=*.scss && \ python manage.py collectstatic --ignore=*.scss && \
python manage.py compilescss --delete-files python manage.py compilescss --delete-files

View file

@ -3,6 +3,13 @@
version=$(<version.txt) version=$(<version.txt)
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 \ docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 \
-f docker/default.Dockerfile \
-t sissbruecker/linkding:latest \ -t sissbruecker/linkding:latest \
-t sissbruecker/linkding:$version \ -t sissbruecker/linkding:$version \
--push . --push .
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 \
-f docker/alpine.Dockerfile \
-t sissbruecker/linkding:latest-alpine \
-t sissbruecker/linkding:$version-alpine \
--push .

View file

@ -1,6 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
docker build -t sissbruecker/linkding:local . variant="${1:-default}"
docker build -f "docker/$variant.Dockerfile" -t sissbruecker/linkding:local .
docker rm -f linkding-local || true docker rm -f linkding-local || true