diff --git a/.hadolint.yaml b/.hadolint.yaml index 3d6d83e9da..11ee226343 100644 --- a/.hadolint.yaml +++ b/.hadolint.yaml @@ -2,3 +2,4 @@ ignored: - DL3006 - DL3008 + - DL3013 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aa5faab5c3..c3ca4a0762 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -72,6 +72,16 @@ repos: - id: hadolint-docker entry: hadolint/hadolint:v2.12.1-beta hadolint + # Lint: Dockerfile + # We're linting .dockerfile files as well + - repo: https://github.com/hadolint/hadolint.git + rev: v2.12.1-beta + hooks: + - id: hadolint-docker + entry: hadolint/hadolint:v2.12.1-beta hadolint + types: [file] + files: \.dockerfile$ + # Lint: YAML - repo: https://github.com/adrienverge/yamllint.git rev: v1.32.0 diff --git a/docs/contributing/lint.md b/docs/contributing/lint.md index 4fb83bf7e3..1b213d0572 100644 --- a/docs/contributing/lint.md +++ b/docs/contributing/lint.md @@ -50,6 +50,7 @@ The following rules are ignored by default for all images in the `.hadolint.yaml - `base-notebook` `FROM` clause is fixed but based on an argument (`ARG`). - Building downstream images from (`FROM`) the latest is done on purpose. - [`DL3008`][dl3008]: System packages are always updated (`apt-get`) to the latest version. +- [`DL3013`][dl3013]: We always install latest packages using `pip` The preferred way to do it for other rules is to flag ignored ones in the `Dockerfile`. @@ -69,4 +70,5 @@ RUN cd /tmp && echo "hello!" [rules]: https://github.com/hadolint/hadolint#rules [dl3006]: https://github.com/hadolint/hadolint/wiki/DL3006 [dl3008]: https://github.com/hadolint/hadolint/wiki/DL3008 +[dl3013]: https://github.com/hadolint/hadolint/wiki/DL3013 [pre-commit]: https://pre-commit.com/ diff --git a/docs/using/recipe_code/dask_jupyterlab.dockerfile b/docs/using/recipe_code/dask_jupyterlab.dockerfile new file mode 100644 index 0000000000..e9cb281e2f --- /dev/null +++ b/docs/using/recipe_code/dask_jupyterlab.dockerfile @@ -0,0 +1,10 @@ +FROM jupyter/base-notebook + +# Install the Dask dashboard +RUN mamba install --yes 'dask-labextension' && \ + mamba clean --all -f -y && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" + +# Dask Scheduler port +EXPOSE 8787 diff --git a/docs/using/recipe_code/jupyterhub_version.dockerfile b/docs/using/recipe_code/jupyterhub_version.dockerfile new file mode 100644 index 0000000000..8704ded1a5 --- /dev/null +++ b/docs/using/recipe_code/jupyterhub_version.dockerfile @@ -0,0 +1,6 @@ +FROM jupyter/base-notebook + +RUN mamba install --yes 'jupyterhub==4.0.1' && \ + mamba clean --all -f -y && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" diff --git a/docs/using/recipe_code/mamba_install.dockerfile b/docs/using/recipe_code/mamba_install.dockerfile new file mode 100644 index 0000000000..05e20bd91a --- /dev/null +++ b/docs/using/recipe_code/mamba_install.dockerfile @@ -0,0 +1,13 @@ +FROM jupyter/base-notebook + +RUN mamba install --yes 'flake8' && \ + mamba clean --all -f -y && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" + +# Install from the requirements.txt file +COPY --chown=${NB_UID}:${NB_GID} requirements.txt /tmp/ +RUN mamba install --yes --file /tmp/requirements.txt && \ + mamba clean --all -f -y && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" diff --git a/docs/using/recipe_code/manpage_install.dockerfile b/docs/using/recipe_code/manpage_install.dockerfile new file mode 100644 index 0000000000..d3043258a1 --- /dev/null +++ b/docs/using/recipe_code/manpage_install.dockerfile @@ -0,0 +1,16 @@ +FROM jupyter/base-notebook + +# Fix: https://github.com/hadolint/hadolint/wiki/DL4006 +# Fix: https://github.com/koalaman/shellcheck/wiki/SC3014 +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +USER root + +# `/etc/dpkg/dpkg.cfg.d/excludes` contains several `path-exclude`s, including man pages +# Remove it, then install man, install docs +RUN rm /etc/dpkg/dpkg.cfg.d/excludes && \ + apt-get update --yes && \ + dpkg -l | grep ^ii | cut -d' ' -f3 | xargs apt-get install --yes --no-install-recommends --reinstall man && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +USER ${NB_UID} diff --git a/docs/using/recipe_code/microsoft_odbc.dockerfile b/docs/using/recipe_code/microsoft_odbc.dockerfile new file mode 100644 index 0000000000..36cfc068ac --- /dev/null +++ b/docs/using/recipe_code/microsoft_odbc.dockerfile @@ -0,0 +1,30 @@ +FROM jupyter/base-notebook + +# Fix: https://github.com/hadolint/hadolint/wiki/DL4006 +# Fix: https://github.com/koalaman/shellcheck/wiki/SC3014 +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +USER root + +ENV MSSQL_DRIVER "ODBC Driver 18 for SQL Server" +ENV PATH="/opt/mssql-tools18/bin:${PATH}" + +RUN apt-get update --yes && \ + apt-get install --yes --no-install-recommends curl gnupg2 lsb-release && \ + curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \ + curl "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list" > /etc/apt/sources.list.d/mssql-release.list && \ + apt-get update --yes && \ + ACCEPT_EULA=Y apt-get install --yes --no-install-recommends msodbcsql18 && \ + # optional: for bcp and sqlcmd + ACCEPT_EULA=Y apt-get install --yes --no-install-recommends mssql-tools18 && \ + # optional: for unixODBC development headers + apt-get install --yes --no-install-recommends unixodbc-dev && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +# Switch back to jovyan to avoid accidental container runs as root +USER ${NB_UID} + +RUN mamba install --yes 'pyodbc' && \ + mamba clean --all -f -y && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" diff --git a/docs/using/recipe_code/pip_install.dockerfile b/docs/using/recipe_code/pip_install.dockerfile new file mode 100644 index 0000000000..60fbd46dee --- /dev/null +++ b/docs/using/recipe_code/pip_install.dockerfile @@ -0,0 +1,12 @@ +FROM jupyter/base-notebook + +# Install in the default python3 environment +RUN pip install --no-cache-dir 'flake8' && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" + +# Install from the requirements.txt file +COPY --chown=${NB_UID}:${NB_GID} requirements.txt /tmp/ +RUN pip install --no-cache-dir --requirement /tmp/requirements.txt && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" diff --git a/docs/using/recipe_code/rise_jupyterlab.dockerfile b/docs/using/recipe_code/rise_jupyterlab.dockerfile new file mode 100644 index 0000000000..e665b8e9b7 --- /dev/null +++ b/docs/using/recipe_code/rise_jupyterlab.dockerfile @@ -0,0 +1,6 @@ +FROM jupyter/base-notebook + +RUN mamba install --yes 'jupyterlab_rise' && \ + mamba clean --all -f -y && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" diff --git a/docs/using/recipe_code/xgboost.dockerfile b/docs/using/recipe_code/xgboost.dockerfile new file mode 100644 index 0000000000..8b762ff684 --- /dev/null +++ b/docs/using/recipe_code/xgboost.dockerfile @@ -0,0 +1,6 @@ +FROM jupyter/base-notebook + +RUN mamba install --yes 'py-xgboost' && \ + mamba clean --all -f -y && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${NB_USER}" diff --git a/docs/using/recipes.md b/docs/using/recipes.md index 426198f613..f4477f1262 100644 --- a/docs/using/recipes.md +++ b/docs/using/recipes.md @@ -28,37 +28,14 @@ See [Docker security documentation](https://docs.docker.com/engine/security/user Create a new Dockerfile like the one shown below. To use a requirements.txt file, first, create your `requirements.txt` file with the listing of packages desired. -```dockerfile -FROM jupyter/base-notebook - -RUN mamba install --yes 'flake8' && \ - mamba clean --all -f -y && \ - fix-permissions "${CONDA_DIR}" && \ - fix-permissions "/home/${NB_USER}" - -# Install from the requirements.txt file -COPY --chown=${NB_UID}:${NB_GID} requirements.txt /tmp/ -RUN mamba install --yes --file /tmp/requirements.txt && \ - mamba clean --all -f -y && \ - fix-permissions "${CONDA_DIR}" && \ - fix-permissions "/home/${NB_USER}" +```{literalinclude} recipe_code/mamba_install.dockerfile +:language: docker ``` `pip` usage is similar: -```dockerfile -FROM jupyter/base-notebook - -# Install in the default python3 environment -RUN pip install --no-cache-dir 'flake8' && \ - fix-permissions "${CONDA_DIR}" && \ - fix-permissions "/home/${NB_USER}" - -# Install from the requirements.txt file -COPY --chown=${NB_UID}:${NB_GID} requirements.txt /tmp/ -RUN pip install --no-cache-dir --requirement /tmp/requirements.txt && \ - fix-permissions "${CONDA_DIR}" && \ - fix-permissions "/home/${NB_USER}" +```{literalinclude} recipe_code/pip_install.dockerfile +:language: docker ``` Then build a new image. @@ -108,17 +85,8 @@ RUN "${CONDA_DIR}/envs/${conda_env}/bin/python" -m ipykernel install --user --na [Dask JupyterLab Extension](https://github.com/dask/dask-labextension) provides a JupyterLab extension to manage Dask clusters, as well as embed Dask's dashboard plots directly into JupyterLab panes. Create the Dockerfile as: -```dockerfile -FROM jupyter/base-notebook - -# Install the Dask dashboard -RUN mamba install --yes 'dask-labextension' && \ - mamba clean --all -f -y && \ - fix-permissions "${CONDA_DIR}" && \ - fix-permissions "/home/${NB_USER}" - -# Dask Scheduler port -EXPOSE 8787 +```{literalinclude} recipe_code/dask_jupyterlab.dockerfile +:language: docker ``` And build the image as: @@ -153,24 +121,14 @@ We're providing the recipe to install JupyterLab extension. You can find the original Jupyter Notebook extenstion [here](https://github.com/damianavila/RISE) ``` -```dockerfile -FROM jupyter/base-notebook - -RUN mamba install --yes 'jupyterlab_rise' && \ - mamba clean --all -f -y && \ - fix-permissions "${CONDA_DIR}" && \ - fix-permissions "/home/${NB_USER}" +```{literalinclude} recipe_code/rise_jupyterlab.dockerfile +:language: docker ``` ## xgboost -```dockerfile -FROM jupyter/base-notebook - -RUN mamba install --yes 'py-xgboost' && \ - mamba clean --all -f -y && \ - fix-permissions "${CONDA_DIR}" && \ - fix-permissions "/home/${NB_USER}" +```{literalinclude} recipe_code/xgboost.dockerfile +:language: docker ``` ## Running behind an nginx proxy @@ -202,19 +160,8 @@ Ref: Most containers, including our Ubuntu base image, ship without manpages installed to save space. You can use the following Dockerfile to inherit from one of our images to enable manpages: -```dockerfile -FROM jupyter/base-notebook - -USER root - -# `/etc/dpkg/dpkg.cfg.d/excludes` contains several `path-exclude`s, including man pages -# Remove it, then install man, install docs -RUN rm /etc/dpkg/dpkg.cfg.d/excludes && \ - apt-get update --yes && \ - dpkg -l | grep ^ii | cut -d' ' -f3 | xargs apt-get install --yes --no-install-recommends --reinstall man && \ - apt-get clean && rm -rf /var/lib/apt/lists/* - -USER ${NB_UID} +```{literalinclude} recipe_code/manpage_install.dockerfile +:language: docker ``` Adding the documentation on top of the existing image wastes a lot of space @@ -254,13 +201,8 @@ Credit: [Justin Tyberg](https://github.com/jtyberg), [quanghoc](https://github.c To use a specific version of JupyterHub, the version of `jupyterhub` in your image should match the version in the Hub itself. -```dockerfile -FROM jupyter/base-notebook - -RUN mamba install --yes 'jupyterhub==4.0.1' && \ - mamba clean --all -f -y && \ - fix-permissions "${CONDA_DIR}" && \ - fix-permissions "/home/${NB_USER}" +```{literalinclude} recipe_code/jupyterhub_version.dockerfile +:language: docker ``` ## Spark @@ -555,33 +497,8 @@ RUN ijsinstall The following recipe demonstrates how to add functionality to read from and write to an instance of Microsoft SQL server in your notebook. -```dockerfile -FROM jupyter/base-notebook - -USER root - -ENV MSSQL_DRIVER "ODBC Driver 18 for SQL Server" -ENV PATH="/opt/mssql-tools18/bin:${PATH}" - -RUN apt-get update --yes && \ - apt-get install --yes --no-install-recommends curl gnupg2 lsb-release && \ - curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \ - curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list > /etc/apt/sources.list.d/mssql-release.list && \ - apt-get update --yes && \ - ACCEPT_EULA=Y apt-get install --yes --no-install-recommends msodbcsql18 && \ - # optional: for bcp and sqlcmd - ACCEPT_EULA=Y apt-get install --yes --no-install-recommends mssql-tools18 && \ - # optional: for unixODBC development headers - apt-get install -y unixodbc-dev && \ - apt-get clean && rm -rf /var/lib/apt/lists/* - -# Switch back to jovyan to avoid accidental container runs as root -USER ${NB_UID} - -RUN mamba install --yes 'pyodbc' && \ - mamba clean --all -f -y && \ - fix-permissions "${CONDA_DIR}" && \ - fix-permissions "/home/${NB_USER}" +```{literalinclude} recipe_code/microsoft_odbc.dockerfile +:language: docker ``` You can now use `pyodbc` and `sqlalchemy` to interact with the database. diff --git a/tensorflow-notebook/Dockerfile b/tensorflow-notebook/Dockerfile index 24a46d96fe..51070fdc8e 100644 --- a/tensorflow-notebook/Dockerfile +++ b/tensorflow-notebook/Dockerfile @@ -11,7 +11,6 @@ LABEL maintainer="Jupyter Project " SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install Tensorflow with pip -# hadolint ignore=DL3013 RUN pip install --no-cache-dir tensorflow && \ fix-permissions "${CONDA_DIR}" && \ fix-permissions "/home/${NB_USER}"