Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify Dockerfile and narrow context #580

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# Ignoring files that are specific to a given checkout, these change based on
# the user commands and not on the repository history. They are not important
# to determine the state of the repository and would invalidate the cache
# layer.
#
# - .git/logs/HEAD - command history
# - .git/index - binary file for the current index, very important for a
# working repository, not interesting for our image
#
.git/logs/HEAD
.git/index
# Ignore everything by default. Making as few files as possible part of default context
# ensures only relevant changes will evict layer cache.
*

# Include source directories and files required for building.
!karapace
!requirements.txt
!setup.py
!version.py
!README.rst
!container/start.sh

# Ignore some files in source directories.
**/.DS_Store
**/Thumbs.db
**/*.pyc
**/*.pyo
**/__pycache__
3 changes: 3 additions & 0 deletions .github/workflows/container-smoke-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3

- name: Build karapace/version.py
run: python version.py

- name: Build and start services
run: docker compose --file=container/compose.yml up --build --wait --detach

Expand Down
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ repos:
- id: mypy
pass_filenames: false

- repo: https://github.com/hadolint/hadolint
rev: v2.12.0
hooks:
- id: hadolint-docker
alias: hadolint
args:
# This rule has false positives when using a mounted cache volume.
# https://github.com/hadolint/hadolint/issues/497
- --ignore=DL3042

- repo: https://github.com/PyCQA/pylint
# Note: pre-commit autoupdate changes to an alpha version. Instead, manually find the
# latest stable version here: https://github.com/pylint-dev/pylint/releases
Expand Down
58 changes: 22 additions & 36 deletions container/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,56 +1,42 @@
# Builder image contains header files and additional dependencies necessary to
# generate wheel files.
FROM debian:stable-slim AS builder
# Current versions of avro and zstandard don't yet have wheels for 3.11.
FROM python:3.10.11-bullseye AS builder

ARG KARAPACE_VERSION

# Build dependencies that need to be installed:
# - git: Used to install dependencies directly from their public repos (release
# not on PyPI).
# - python3-devel: Python .h files, used to compile C extensions (e.g. multidict)
#
# Build dependencies that need to be installed because of `--no-install-recommends`:
# - gcc: g++ and gcc to compile C extensions
# - python3-wheel: Library to generate .whl files
# - python3-setuptools: Packaging library
#
RUN apt-get update && \
apt-get -y install --no-install-recommends git python3-dev python3-pip python3-setuptools python3-wheel gcc && \
rm -rf /var/lib/apt/lists/*
# Create, activate, and enforce usage of virtualenv.
RUN python3 -m venv /venv
ENV PATH="/venv/bin:$PATH"
ENV PIP_REQUIRE_VIRTUALENV=true

# Copy the requirements.txt and generate wheels for each dependency. Using a
# separate command to use layer caching.
# Copy the requirements.txt and install dependencies in venv. Using a separate
# command to use layer caching.
#
# Note: the requirements.txt is pinned, if any of the dependencies is updated
# the cache will be invalidated and the image regenerated, which is the
# intended behavior.
#
COPY ./requirements/requirements.txt /build/
RUN pip3 wheel --requirement /build/requirements.txt --wheel-dir /build/dependencies-wheels
RUN --mount=type=cache,target=/root/.cache/pip \
python3 -m pip install -r /build/requirements.txt

COPY . /build/karapace-repo
RUN pip3 wheel --no-deps /build/karapace-repo --wheel-dir /build/karapace-wheel
RUN --mount=type=cache,target=/root/.cache/pip \
python3 -m pip install /build/karapace-repo

# Karapace image.
FROM debian:stable-slim AS karapace

RUN groupadd --system karapace && \
useradd --system --gid karapace karapace && \
mkdir /opt/karapace /opt/karapace/runtime /var/log/karapace && \
chown --recursive karapace:karapace /opt/karapace /var/log/karapace

RUN apt-get update && \
apt-get -y install --no-install-recommends python3-pip protobuf-compiler && \
rm -rf /var/lib/apt/lists/*
FROM python:3.10.11-slim-bullseye AS karapace

COPY --from=builder /build/dependencies-wheels/*.whl /build/dependencies-wheels/
RUN pip3 install --no-deps /build/dependencies-wheels/*.whl && rm -rf /build/dependencies-wheels/
RUN groupadd --system karapace \
&& useradd --system --gid karapace karapace \
&& mkdir /opt/karapace /opt/karapace/runtime /var/log/karapace \
&& chown --recursive karapace:karapace /opt/karapace /var/log/karapace

COPY --from=builder /build/karapace-wheel/*.whl /build/karapace-wheel/
RUN pip3 install --no-deps /build/karapace-wheel/*.whl && rm -rf /build/karapace-wheel/
# Copy virtualenv from builder and activate it.
COPY --from=builder /venv /venv
ENV PATH="/venv/bin:$PATH"

COPY ./container/start.sh /opt/karapace
RUN chmod 500 /opt/karapace/start.sh && chown karapace:karapace /opt/karapace/start.sh
RUN chmod 500 /opt/karapace/start.sh \
&& chown karapace:karapace /opt/karapace/start.sh

COPY ./container/healthcheck.py /opt/karapace

Expand Down
2 changes: 1 addition & 1 deletion container/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ registry)
[[ -n ${KARAPACE_REGISTRY_PORT+isset} ]] && export KARAPACE_PORT="${KARAPACE_REGISTRY_PORT}"
[[ -n ${KARAPACE_REGISTRY_CLIENT_ID+isset} ]] && export KARAPACE_CLIENT_ID="${KARAPACE_REGISTRY_CLIENT_ID}"
[[ -n ${KARAPACE_REGISTRY_GROUP_ID+isset} ]] && export KARAPACE_GROUP_ID="${KARAPACE_REGISTRY_GROUP_ID}"
# Map misspelt environment variable to correct spelling for backwards compatibility.
# Map misspelled environment variables to correct spelling for backwards compatibility.
[[ -n ${KARAPACE_REGISTRY_MASTER_ELIGIBITY+isset} ]] && export KARAPACE_MASTER_ELIGIBILITY="${KARAPACE_REGISTRY_MASTER_ELIGIBITY}"
[[ -n ${KARAPACE_REGISTRY_MASTER_ELIGIBILITY+isset} ]] && export KARAPACE_MASTER_ELIGIBILITY="${KARAPACE_REGISTRY_MASTER_ELIGIBILITY}"
[[ -n ${KARAPACE_REGISTRY_TOPIC_NAME+isset} ]] && export KARAPACE_TOPIC_NAME="${KARAPACE_REGISTRY_TOPIC_NAME}"
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
with open(readme_path, encoding="utf8") as fp:
readme_text = fp.read()

version_for_setup_py = version.get_project_version("karapace/version.py")
version_for_setup_py = version.get_project_version()
version_for_setup_py = ".dev".join(version_for_setup_py.split("-", 2)[:2])

setup(
Expand Down
37 changes: 22 additions & 15 deletions version.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,35 @@
Copyright (c) 2023 Aiven Ltd
See LICENSE for details
"""
import importlib.util
from __future__ import annotations

from typing import Final

import os
import pathlib
import subprocess

version_file: Final = pathlib.Path(__file__).parent.resolve() / "karapace/version.py"


def save_version(new_ver, old_ver, version_file):
def save_version(new_ver, old_ver):
if not new_ver:
return False
version_file = os.path.join(os.path.dirname(__file__), version_file)
if not old_ver or new_ver != old_ver:
with open(version_file, mode="w", encoding="utf8") as fp:
fp.write(f'"""{__doc__}"""\n__version__ = "{new_ver}"\n')
version_file.write_text(f'"""{__doc__}"""\n__version__ = "{new_ver}"\n')
return True


def get_project_version(version_file: str) -> str:
version_file_full_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), version_file)
module_spec = importlib.util.spec_from_file_location("verfile", version_file_full_path)
module = importlib.util.module_from_spec(module_spec)
file_ver = getattr(module, "__version__", None)
def from_version_file() -> str | None:
try:
import karapace.version
except ImportError:
return None
return karapace.version.__version__


def get_project_version() -> str:
file_ver = from_version_file()

version = os.getenv("KARAPACE_VERSION")
if version is None:
Expand All @@ -40,16 +49,14 @@ def get_project_version(version_file: str) -> str:
git_ver = f"0.0.1-0-unknown-{git_ver}"
version = git_ver

if save_version(version, file_ver, version_file):
if save_version(version, file_ver):
return version

if not file_ver:
raise RuntimeError(f"version not available from git or from file {version_file!r}")
raise RuntimeError(f"version not available from git or from file {str(version_file)!r}")

return file_ver


if __name__ == "__main__":
import sys

get_project_version(sys.argv[1])
get_project_version()