Docker multistage build Issues - docker

My Current Docker file looks like below . I'm trying to use h2o as a base for my ML model service .Now h2o requires JRE and i'm forced to install the required packages for my flask script . It was as heavy as 1.8 Gig so attempted multi-stage build (script below )
#Original Docker File
FROM h2oai/h2o-open-source-k8s
MAINTAINER rajesh.r6r#gmail.com
USER root
WORKDIR /app
ADD . /app
RUN set -xe \
&& apt-get update -y \
&& apt-get install python-pip -y \
&& rm -rf /var/lib/apt/lists/* # remove the cached files
RUN pip install --upgrade pip
RUN pip install --trusted-host pypi.python.org -r requirements.txt
EXPOSE 5005
EXPOSE 54321
ENV NAME World
CMD ["python", "app.py"]
I attempted doing multi-stage builds as follows , but this only results in a python image skipping the h2o part . What am I Missing ?
#Multi-Stage Docker File
FROM h2oai/h2o-open-source-k8s AS baseimage
FROM python:3.7-slim
USER root
WORKDIR /app
ADD . /app
RUN pip install --trusted-host pypi.python.org -r requirements.txt
EXPOSE 5005
EXPOSE 54321
ENV NAME World
CMD ["python", "app.py"]

Related

Setting up Dockerfile to use non-root user

I'm currently having an issue when I tried to run pip as a non-root user in my Dockerfile. When It starts to build the wheel it gives these warnings WARNING: The script foo is installed in '/home/myuser/.local/bin' which is not on PATH. for pep8, sqlformat, isort, gunicorn, django-admin, epylint, pylint, pyreverse, and symilar.
In the current code I have, the build fails with the error COPY failed: stat usr/src/app/wheels: file does not exist when it tries to run COPY --from=builder /usr/src/app/wheels /wheels although it was failing earlier before I took out --wheel-dir /usr/src/app/wheels from line 35.
###########
# BUILDER #
###########
# pull official base image
FROM python:3.9.4-alpine as builder
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install psycopg2 dependencies
RUN apk update \
&& apk add postgresql-dev gcc python3-dev musl-dev
# lint
RUN pip install --upgrade pip
RUN pip install flake8==3.9.2
COPY . .
RUN flake8 --ignore=E501,F401 .
# install dependencies
RUN adduser -D myuser
USER myuser
WORKDIR /home/myuser
COPY --chown=myuser:myuser requirements.txt requirements.txt
RUN pip install --user -r requirements.txt
ENV PATH="/home/myuser/.local/bin:${PATH}"
COPY --chown=myuser:myuser . .
WORKDIR /usr/src/app
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt
#########
# FINAL #
#########
# pull official base image
FROM python:3.9.4-alpine
# create directory for the app user
RUN mkdir -p /home/app
# create the app user
RUN addgroup -S app && adduser -S app -G app
# create the appropriate directories
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
RUN mkdir $APP_HOME/staticfiles
RUN mkdir $APP_HOME/mediafiles
WORKDIR $APP_HOME
# install dependencies
RUN apk update && apk add libpq
COPY --from=builder /usr/src/app/wheels /wheels
COPY --from=builder /usr/src/app/requirements.txt .
RUN pip install --upgrade pip
RUN pip install --no-cache /wheels/*
# copy entrypoint.prod.sh
COPY ./entrypoint.prod.sh .
RUN sed -i 's/\r$//g' $APP_HOME/entrypoint.prod.sh
RUN chmod +x $APP_HOME/entrypoint.prod.sh
# copy project
COPY . $APP_HOME
# copy media files
COPY ./media/ $APP_HOME/mediafiles
# chown all the files to the app user
RUN chown -R app:app $APP_HOME
# change to the app user
USER app
# run entrypoint.prod.sh
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]
I've tried tinkering with the WORKDIR, ENV PATH, and RUN pip wheel.

Docker Stuck to build Conv2D model

shortcut = tensorflow.keras.layers.Conv2D(filters, 1, strides=stride, use_bias=False, kernel_initializer='glorot_normal', name=name + '_0_conv')(x)
where filters are 64 stride is 2 and name is conv2_block1
this line works perfectly fine in local machine but gets stuck in docker
Below is my docker file attached.
FROM python:3.7.9-buster
RUN apt-get update \
&& apt-get install -y -qq \
&& apt install cmake -y \
&& apt-get install ffmpeg libsm6 libxext6 -y\
&& apt-get clean
RUN pip3 install --upgrade pip
# Install libraries
COPY ./requirements.txt ./
RUN pip install -r requirements.txt && \
rm ./requirements.txt
RUN pip install fire
# Setup container directories
RUN mkdir /app
# Copy local code to the container
COPY . /app
# launch server with gunicorn
WORKDIR /app
EXPOSE 8080
ENV PORT 8080
ENV FLASK_CONF config.ProductionConfig
# CMD ["gunicorn", "main:app", "--timeout=60", "--preload", \
# "--workers=1", "--threads=4", "--bind :$PORT"]
CMD exec gunicorn --bind :$PORT main:app --preload --workers 9 --threads 5 --timeout 120
And these are my requirements.txt
opencv-python
tensorflow==2.2.0
protobuf==3.20.*
cmake
dlib
numpy==1.16.*
The stuck up issue was due to the exhausting resources for the thread, so removing the --preload argument did the job as the models will be executed on the runtime.

Make Docker Container secure as possible

I am looking for a way to make docker images secure as possible. Maybe there is a way to prevent the execution of any process other than specified in CMD?
For example I run the following image, but once a hacker would be able to get into the container he/she could create a python file and do mostly anything with the data in the container.
I also see that wget is available, so the attacker could also easily download his/her files and start sending data to his home. Any tips are welcome.
FROM python:alpine3.16 as builder
RUN pip install --upgrade pip
WORKDIR /opt/working-files
COPY requirements.txt .
RUN python -m venv ./venv
ENV PATH="/opt/working-files/venv/bin:$PATH"
RUN pip install -r requirements.txt
RUN rm -rf requirements.txt && rm -rf ~/.cache/pip
COPY app/ ./app
FROM python:alpine3.16
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV PATH="/opt/working-files/venv/bin:$PATH"
RUN addgroup -S 10033 && adduser -S 10033 -G 10033
USER 10033:10033
COPY --from=builder /opt /opt
WORKDIR /opt/working-files/app
CMD ["gunicorn", "-b", "0.0.0.0:8000", "-w", "1", "app:app"]

RUN addgroup / adduser. Get: Option s is ambiguous (shell, system) error

I am Dockerising my first flask app and following an online guide but stuck with the following line in Dockerfile.prod.
RUN addgroup -S app && adduser -S app -G app
I get the error Option s is ambiguous (shell, system)
I came across this SO post and tried the accepted answer (pretty much the same):
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
With the same outcome. I have tried specifying --shell and --system, and --group instead get the error addgroup: Only one or two names allowed.
No matter what I try, I get these errors:
Option s is ambiguous (shell, system)
Option g is ambiguous (gecos, gid, group)
I am on Windows (using Docker, not Docker Windows). Not sure if that's the issue. But I cannot find a solution.
Dockerfile.prod
FROM python:3.8.1-slim-buster as builder
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install system dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc
# lint
RUN pip install --upgrade pip
RUN pip install flake8
COPY . /usr/src/app/
RUN flake8 --ignore=E501,F401,E722 .
# install python dependencies
COPY ./requirements.txt .
# COPY requirements .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt
# RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements/prod.txt
# pull official base image
FROM python:3.8.1-slim-buster
# create directory for the app user
RUN mkdir -p /home/app
# create the app user
RUN addgroup -S app && adduser -S app -G app
# create the appropriate directories
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
# install dependencies
RUN apt-get update && apt-get install -y --no-install-recommends netcat
COPY --from=builder /usr/src/app/wheels /wheels
COPY --from=builder /usr/src/app/requirements.txt .
# COPY --from=builder /usr/src/app/requirements/common.txt .
# COPY --from=builder /usr/src/app/requirements/prod.txt .
RUN pip install --upgrade pip
RUN pip install --no-cache /wheels/*
# copy entrypoint-prod.sh
COPY ./entrypoint.prod.sh $APP_HOME
# copy project
COPY . $APP_HOME
# chown all the files to the app user
RUN chown -R app:app $APP_HOME
# change to the app user
USER app
# run entrypoint.prod.sh
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]
I do understand you would like to create a user and group both called "app" and the user shall be in that group, both being a system account/group.
That's possible by online using adduser
RUN adduser --system --group app
Maybe this helps:
https://github.com/mozilla-services/Dockerflow/issues/36
Depending on the underlying distribution of the container, these
options can be ambiguous. The options should use the full name format
for readability.

Docker copy src

My project hierarchy is as such:
docker-flowcell-restore
docker-flowcell-restore
config
src
requirements.txt
Dockerfile
I would like to add my src file to my docker image using Copy. So far my Docker image has the following:
FROM ubuntu
RUN apt-get update && apt-get install -y \
python3 \
python3-pip
ENV INSTALL_PATH /docker-flowcell-restore
RUN mkdir -p $INSTALL_PATH
WORKDIR $INSTALL_PATH
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
ENTRYPOINT ['python', 'docker-flowcell-restore/src/main.py']
How do I add the copy of the contents of the src folder? Thank you.
Add the copy after your pip install command. This leverages the docker layer cache so you don't rerun the install of all the requirements after a change to different parts of your code:
FROM ubuntu
RUN apt-get update \
&& apt-get install -y \
python3 \
python3-pip \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ENV INSTALL_PATH /docker-flowcell-restore
RUN mkdir -p $INSTALL_PATH
WORKDIR $INSTALL_PATH
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY src/ src/
ENTRYPOINT ['python', 'src/main.py']
I've also added steps to cleanup the apt cache after performing the install, and adjusted the entrypoint since the WORKDIR was defined.
You can do the following:
FROM ubuntu
RUN apt-get update && apt-get install -y \
python3 \
python3-pip
ENV INSTALL_PATH /docker-flowcell-restore
RUN mkdir -p $INSTALL_PATH
WORKDIR $INSTALL_PATH
COPY requirements.txt requirements.txt
COPY ./src <the path inside the container where you want src>
RUN pip install -r requirements.txt
ENTRYPOINT ['python', 'docker-flowcell-restore/src/main.py']
This is assuming that you are building your image from the directory where the Dockerfile is located.

Resources