znat
znat

Reputation: 13474

How to set the python root to the Dockerfile workdir

I have a simple Dockerfile:

FROM python:3.6-alpine
RUN apk add -U --no-cache gcc build-base linux-headers ca-certificates python3-dev libffi-dev libressl-dev libxslt-dev
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . app/
WORKDIR /app

ENV FLASK_APP app.py

EXPOSE 5000
ENTRYPOINT [ "python" ]

CMD ["-m", "flask", "run"]

When I run the app locally (not in docker) everything is fine. However, because the whole app is moved to the /app workdir, modules are not recognized anymore. I need to do this to make it work:

from app.my_module import MyClass

How do I tell python the root is /app and not /?

Upvotes: 0

Views: 3912

Answers (1)

Exadra37
Exadra37

Reputation: 13084

The Problem

ENV FLASK_APP app.py

Change it to:

ENV FLASK_APP=/app/app.py

CMD ["-m", "flask", "run"]

You only need flask run -h 0.0.0.0 not python -m flask run... and if you do it so you may remove entirely the ENTRYPOINT line or instead add the flask instruction to the ENTRYPOINT and remove the CMD one.

-h 0.0.0.0 is needed when running inside a container, otherwise it will bind to 127.0.0.1 that is localhost inside the container, therefor not accessible from your host computer browser.

ENTRYPOINT [ "python" ]

You are installing Python 3 stuff but then you seem to be using Python 2... Check that python is really pointing to the Python version you intend to run your app in.

Security

Never run applications inside a docker container as root, just like you wouldn't do in a bare metal server or in a VPS. Just create a normal user and run the application in unprivileged way.

A better solution

Use instead this Dockerfile for a Python server as an inspiration for your use case.

Just adapt the Dockerfile to start from alpine and replace the commands for ubuntu by the equivalent ones in Alpine.

FROM ubuntu:18.04

ARG CONTAINER_USER="python"
ARG CONTAINER_UID="1000"
ARG DISPLAY=":0.0"
ARG ZSH_THEME="robbyrussell"

# Will not prompt for questions
ENV DEBIAN_FRONTEND=noninteractive \
    CONTAINER_USER=python \
    CONTAINER_UID=1000 \
    ROOT_CA_DIR=/root-ca/ \
    PROXY_CA_FILENAME="FirewallProxyCA.crt" \
    PROXY_CA_PEM="certificates/FirewallProxyCA.crt" \
    PROXY_CA_NAME="FirewallProxy"

COPY ./setup ${ROOT_CA_DIR}

RUN apt update && \
    apt -y upgrade && \
    apt -y install \
      ca-certificates \
      locales \
      tzdata \
      inotify-tools \
      libnss3-tools \
      curl \
      git \
      zsh \
      unzip \
      libxss1 \
      python-pip \
      python3-pip && \

    locale-gen en_GB.UTF-8 && \
    dpkg-reconfigure locales && \

    #https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers
    printf "fs.inotify.max_user_watches=524288\n" >> /etc/sysctl.conf && \

    useradd -m -u ${CONTAINER_UID} -s /bin/bash ${CONTAINER_USER} && \

    cd ${ROOT_CA_DIR} && \
    ./add-proxy-certificate.sh "${PROXY_CA_PEM}" && \

    # Install Oh My Zsh for Root and Node user
    bash -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" && \
    chsh -s /usr/bin/zsh && \
    cp -R /root/.oh-my-zsh /home/"${CONTAINER_USER}" && \
    cp /root/.zsh* /home/"${CONTAINER_USER}" && \
    sed -i "s/\/root/\/home\/${CONTAINER_USER}/g" /home/"${CONTAINER_USER}"/.zshrc && \
    chown -R "${CONTAINER_USER}":"${CONTAINER_USER}" /home/"${CONTAINER_USER}" && \
    sed -i s/ZSH_THEME=\"robbyrussell\"/ZSH_THEME=\"${ZSH_THEME}\"/g /home/${CONTAINER_USER}/.zshrc

ENV LANG=en_GB.UTF-8 \
    LANGUAGE=en_GB:en \
    LC_ALL=en_GB.UTF-8

USER ${CONTAINER_USER}

RUN pip3 install \
      flask \
      pyjwt \
      python-dotenv \
      docopt

# pip install will put the executables under ~/.local/bin
ENV PATH=/home/"${CONTAINER_USER}"/.local/bin:$PATH

WORKDIR /home/${CONTAINER_USER}/workspace

EXPOSE 5000

CMD ["zsh"]

See how is started from this bash script:


#!/bin/bash

set -eu

CONTAINER_USER="$(id -u)"

HTTP_PORT=5000


function Create_Docker_Container
{
    local _command="${1:-zsh}"
    local _user="${2? Missing user name or uid for the container we want to stop!!!}"
    local _port="${3? Missing http port for the container we want to stop!!!}"
    local _server_name="${4? Missing server name for the container we want to stop!!!}"
    local _container_name="python-flask-${_user}-${_server_name}-${_port}"

    sudo docker run \
        -it \
        --rm \
        --user "${_user}" \
        --env-file .env \
        --env "FLASK_APP=server/${_server_name}.py" \
        --env "HTTP_PORT=${_port}" \
        --name "${_container_name}" \
        --publish "127.0.0.1:${_port}:5000" \
        --workdir "/home/python/workspace" \
        --volume "$PWD:/home/python/workspace" \
        approov/python-flask ${_command}
}

Create_Docker_Container "flask run -h 0.0.0.0" "${CONTAINER_USER}" "${HTTP_PORT}" "original-server"

The .env file:

HTTP_PORT=5000
FLASK_APP=server/original-server.py
FLASK_ENV=development

Upvotes: 1

Related Questions