diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..8513c1d3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +.git +slides/ +.DS_Store +__pycache__/ diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml deleted file mode 100644 index 035cb9a9..00000000 --- a/.github/workflows/build-docker-image.yml +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: Build Tutorial Container -on: - push: - branches: - - main - paths-ignore: - - "*.md" - - slides/** - - images/** - - .gitignore - workflow_dispatch: -jobs: - repo2docker: - runs-on: ubuntu-latest - permissions: - packages: write - steps: - - name: checkout files in repo - uses: actions/checkout@main - - name: update jupyter dependencies with repo2docker - uses: jupyterhub/repo2docker-action@master - with: - DOCKER_USERNAME: ${{ github.actor }} - DOCKER_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - DOCKER_REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - FORCE_REPO2DOCKER_VERSION: jupyter-repo2docker==2024.07.0 diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 00000000..5762f13b --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,69 @@ +--- +name: Build Tutorial Container + +on: + push: + branches: + - main + paths-ignore: + - "*.md" + - slides/** + - images/** + - .gitignore + tags: + - "v*.*" + - "v*.*.*" + pull_request: + paths-ignore: + - "*.md" + - slides/** + - images/** + - .gitignore + workflow_dispatch: + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + packages: write + strategy: + matrix: + arch: [amd64, arm64] + fail-fast: false + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} + type=ref,event=pr + type=ref,event=tag + type=sha,format=short + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/${{ matrix.arch }} + push: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..cf496d34 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,48 @@ +# Use the jupyter/minimal-notebook as the base image +FROM quay.io/jupyter/minimal-notebook:latest + +# Metadata labels +LABEL org.opencontainers.image.title="Python Tutorial" +LABEL org.opencontainers.image.description="A containerized Python tutorial environment with Jupyter Lab." +LABEL org.opencontainers.image.authors="Empa Scientific IT " +LABEL org.opencontainers.image.url="https://github.com/empa-scientific-it/python-tutorial" +LABEL org.opencontainers.image.source="https://github.com/empa-scientific-it/python-tutorial" +LABEL org.opencontainers.image.version="1.0.0" +LABEL org.opencontainers.image.licenses="MIT" + +# Set environment variables for the tutorial and repository +ENV BASENAME="python-tutorial" +ENV REPO=${HOME}/${BASENAME} +ENV IPYTHONDIR="${HOME}/.ipython" + +# Switch to root user to install additional dependencies +USER root +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + build-essential \ + gcc \ + g++ \ + libffi-dev \ + libgl1 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Switch back to the default notebook user +USER ${NB_UID} + +# Set up the Conda environment +COPY docker/environment.yml /tmp/environment.yml +RUN mamba env update -n base -f /tmp/environment.yml && \ + mamba clean --all -f -y && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" + +# Prepare IPython configuration (move earlier in the build) +RUN mkdir -p ${HOME}/.ipython/profile_default +COPY --chown=${NB_UID}:${NB_GID} binder/ipython_config.py ${HOME}/.ipython/profile_default/ + +# Set the working directory to the repository +WORKDIR ${REPO} + +# Use the default ENTRYPOINT from the base image to start Jupyter Lab +ENTRYPOINT ["tini", "-g", "--", "start.sh"] diff --git a/README.md b/README.md index b09bbdce..b7bb9520 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ docker pull ghcr.io/empa-scientific-it/python-tutorial:latest 5. Run the Docker container: Once the image is downloaded, run the following command to start a Docker container from the image: ```console -docker run -p 8888:8888 --name python_tutorial -v /path/to/python-tutorial:/home/jovyan/work ghcr.io/empa-scientific-it/python-tutorial:latest jupyter lab --ip 0.0.0.0 --no-browser +docker run -p 8888:8888 --name python_tutorial -v /path/to/python-tutorial:/home/jovyan/python-tutorial ghcr.io/empa-scientific-it/python-tutorial:latest jupyter lab --ip 0.0.0.0 --no-browser ``` Replace `/path/to/python-tutorial` with the path to the folder you created in step 2, for example `C:/Users/yourusername/Desktop/python-tutorial`. diff --git a/docker/environment.yml b/docker/environment.yml new file mode 100644 index 00000000..6df2975c --- /dev/null +++ b/docker/environment.yml @@ -0,0 +1,33 @@ +--- +name: base +channels: + - conda-forge +dependencies: + - pip + - pip: + - numpy + - matplotlib + - pandas + - ipywidgets + - ipynbname + - jupyterlab + - pytest + - pytest-timeout + - markdown + - pre-commit + - geostatspy + - gstools + - scikit-learn + - attrs + - multiprocess + - openai + - tenacity + - markdown2 + - python-dotenv + - pillow + - opencv-python + - torch + - torchaudio + - torchvision + - albumentations + - grad-cam