0

When I run flask run the localhost port is exposed and the application loads with no errors, but when I run docker-compose up -d --build the image is built and running but the localhost is not exposed. inspecting the container shows that it built with no errors and is still running. I've reviewed this github issue and this stackoverflow which suggested network_host mode was the problem but I am not using it. It also suggested manually using 0.0.0.0 instead of 127.0.0.1 in the ports mapping but that didn't help.

docker-compose.yml

#~/Projects/mysite/docker-compose.yml
version: '3.7'
services:
  flask-dev:
    build:
      context: .
      dockerfile: Dockerfile
      target: development
    image: "site-development"
    ports:
      - "5000:5000"
    volumes:
      - ".:/personal_site"
    tty: true

Dockerfile

#~/Projects/mysite/Dockerfile
# multi build stages
#https://docs.docker.com/develop/develop-images/multistage-build/

# ==================================== BASE ====================================
FROM python:3.8-slim-buster AS base

WORKDIR /personal_site

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV FLASK_APP mysite
ENV FLASK_ENV development
ENV FLASK_DEBUG 1


RUN apt-get update
RUN apt-get install -y \
    gcc

RUN pip install --upgrade pip
COPY . .

# ================================= DEVELOPMENT ================================
FROM base as development
COPY ./requirements-dev.txt /personal_site/requirements-dev.txt
RUN pip install -r requirements-dev.txt

CMD ["flask", "run"]

# ================================= PRODUCTION =================================
FROM base as production
COPY ./requirements-prod.txt /personal_site/requirements-prod.txt
RUN pip install -r requirements-prod.txt

# =================================== MANAGE ===================================
FROM base as manage
COPY ./requirements-dev.txt /personal_site/requirements-dev.txt
RUN pip install -r requirements-dev.txt

Docker versions:

docker-compose version 1.25.5, build 8a1c60f6
Docker version 19.03.13, build 4484c46d9d

Folder Structure:

#~/Projects/mysite
- docker-compose.yml
- Dockerfile
- mysite/__init__.py

Running from cmd with flask run

 * Serving Flask app "mysite" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 331-834-605

Docker-compose stout

stephen@stephen:~/Projects/mysite$ docker-compose up -d --build
docker-compose up -d --build
Building flask-dev
Step 1/15 : FROM python:3.8-slim-buster AS base
 ---> 6cf621cb1327
Step 2/15 : WORKDIR /personal_site
 ---> Using cache
 ---> 751c8aa117f3
Step 3/15 : ENV PYTHONDONTWRITEBYTECODE 1
 ---> Using cache
 ---> 8b29a6862b7a
Step 4/15 : ENV PYTHONUNBUFFERED 1
 ---> Using cache
 ---> a5f8751c9c12
Step 5/15 : ENV FLASK_APP mysite
 ---> Using cache
 ---> bc212892cc17
Step 6/15 : ENV FLASK_ENV development
 ---> Using cache
 ---> 9ffa29dcea47
Step 7/15 : ENV FLASK_DEBUG 1
 ---> Using cache
 ---> 9b2e876d307a
Step 8/15 : RUN apt-get update
 ---> Using cache
 ---> bd323216e65a
Step 9/15 : RUN apt-get install -y  gcc
 ---> Using cache
 ---> 3105c1727b5d
Step 10/15 : RUN pip install --upgrade pip
 ---> Using cache
 ---> 6f8fb5bc0015
Step 11/15 : COPY . .
 ---> 76ff5e26c0a9

Step 12/15 : FROM base as development
 ---> 76ff5e26c0a9
Step 13/15 : COPY ./requirements-dev.txt /personal_site/requirements-dev.txt
 ---> 06e9dac6dec6
Step 14/15 : RUN pip install -r requirements-dev.txt
 ---> Running in f4743afd3a31
Collecting click==7.1.2
  Downloading click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting Flask==1.1.2
  Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB)
Collecting itsdangerous==1.1.0
  Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting Jinja2==2.11.2
  Downloading Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting MarkupSafe==1.1.1
  Downloading MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl (32 kB)
Collecting Werkzeug==1.0.1
  Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Collecting pytest==6.0.2
  Downloading pytest-6.0.2-py3-none-any.whl (270 kB)
Collecting black==19.10b0
  Downloading black-19.10b0-py36-none-any.whl (97 kB)
Collecting flake8==3.8.3
  Downloading flake8-3.8.3-py2.py3-none-any.whl (72 kB)
Collecting flake8-blind-except==0.1.1
  Downloading flake8-blind-except-0.1.1.tar.gz (2.5 kB)
Collecting flake8-debugger==3.2.1
  Downloading flake8-debugger-3.2.1.tar.gz (4.2 kB)
Collecting flake8-docstrings==1.5.0
  Downloading flake8_docstrings-1.5.0-py2.py3-none-any.whl (5.5 kB)
Collecting flake8-isort==4.0.0
  Downloading flake8_isort-4.0.0-py2.py3-none-any.whl (14 kB)
Collecting isort==5.5.2
  Downloading isort-5.5.2-py3-none-any.whl (95 kB)
Collecting pep8-naming==0.11.1
  Downloading pep8_naming-0.11.1-py2.py3-none-any.whl (8.4 kB)
Collecting pluggy<1.0,>=0.12
  Downloading pluggy-0.13.1-py2.py3-none-any.whl (18 kB)
Collecting toml
  Downloading toml-0.10.1-py2.py3-none-any.whl (19 kB)
Collecting more-itertools>=4.0.0
  Downloading more_itertools-8.5.0-py3-none-any.whl (44 kB)
Collecting attrs>=17.4.0
  Downloading attrs-20.2.0-py2.py3-none-any.whl (48 kB)
Collecting py>=1.8.2
  Downloading py-1.9.0-py2.py3-none-any.whl (99 kB)
Collecting iniconfig
  Downloading iniconfig-1.0.1-py3-none-any.whl (4.2 kB)
Collecting packaging
  Downloading packaging-20.4-py2.py3-none-any.whl (37 kB)
Collecting appdirs
  Downloading appdirs-1.4.4-py2.py3-none-any.whl (9.6 kB)
Collecting regex
  Downloading regex-2020.9.27-cp38-cp38-manylinux2010_x86_64.whl (675 kB)
Collecting pathspec<1,>=0.6
  Downloading pathspec-0.8.0-py2.py3-none-any.whl (28 kB)
Collecting typed-ast>=1.4.0
  Downloading typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl (768 kB)
Collecting pyflakes<2.3.0,>=2.2.0
  Downloading pyflakes-2.2.0-py2.py3-none-any.whl (66 kB)
Collecting mccabe<0.7.0,>=0.6.0
  Downloading mccabe-0.6.1-py2.py3-none-any.whl (8.6 kB)
Collecting pycodestyle<2.7.0,>=2.6.0a1
  Downloading pycodestyle-2.6.0-py2.py3-none-any.whl (41 kB)
Requirement already satisfied: setuptools in /usr/local/lib/python3.8/site-packages (from flake8-blind-except==0.1.1->-r requirements-dev.txt (line 10)) (50.3.0)
Collecting pydocstyle>=2.1
  Downloading pydocstyle-5.1.1-py3-none-any.whl (35 kB)
Collecting testfixtures<7,>=6.8.0
  Downloading testfixtures-6.14.2-py2.py3-none-any.whl (89 kB)
Collecting flake8-polyfill<2,>=1.0.2
  Downloading flake8_polyfill-1.0.2-py2.py3-none-any.whl (7.3 kB)
Collecting six
  Downloading six-1.15.0-py2.py3-none-any.whl (10 kB)
Collecting pyparsing>=2.0.2
  Downloading pyparsing-2.4.7-py2.py3-none-any.whl (67 kB)
Collecting snowballstemmer
  Downloading snowballstemmer-2.0.0-py2.py3-none-any.whl (97 kB)
Building wheels for collected packages: flake8-blind-except, flake8-debugger
  Building wheel for flake8-blind-except (setup.py): started
  Building wheel for flake8-blind-except (setup.py): finished with status 'done'
  Created wheel for flake8-blind-except: filename=flake8_blind_except-0.1.1-py3-none-any.whl size=3045 sha256=ee8ec372f4ef9ba5aa472cc70cf2b34462c2e5742c4431a88d4811ba3c6941b9
  Stored in directory: /root/.cache/pip/wheels/7f/70/4f/6002af5c24a072eec72570bf0a265bf95f1968c4508563b6cd
  Building wheel for flake8-debugger (setup.py): started
  Building wheel for flake8-debugger (setup.py): finished with status 'done'
  Created wheel for flake8-debugger: filename=flake8_debugger-3.2.1-py3-none-any.whl size=4201 sha256=0399bc5b93a43d4f70912c25e9251000b1003a04215c0d3b0656da88f0fd828b
  Stored in directory: /root/.cache/pip/wheels/39/b8/cc/049c8f7f02a46a88305db6b9ed26799fded45f98e20728640c
Successfully built flake8-blind-except flake8-debugger
Installing collected packages: click, MarkupSafe, Jinja2, Werkzeug, itsdangerous, Flask, pluggy, toml, more-itertools, attrs, py, iniconfig, six, pyparsing, packaging, pytest, appdirs, regex, pathspec, typed-ast, black, pyflakes, mccabe, pycodestyle, flake8, flake8-blind-except, flake8-debugger, snowballstemmer, pydocstyle, flake8-docstrings, isort, testfixtures, flake8-isort, flake8-polyfill, pep8-naming
Successfully installed Flask-1.1.2 Jinja2-2.11.2 MarkupSafe-1.1.1 Werkzeug-1.0.1 appdirs-1.4.4 attrs-20.2.0 black-19.10b0 click-7.1.2 flake8-3.8.3 flake8-blind-except-0.1.1 flake8-debugger-3.2.1 flake8-docstrings-1.5.0 flake8-isort-4.0.0 flake8-polyfill-1.0.2 iniconfig-1.0.1 isort-5.5.2 itsdangerous-1.1.0 mccabe-0.6.1 more-itertools-8.5.0 packaging-20.4 pathspec-0.8.0 pep8-naming-0.11.1 pluggy-0.13.1 py-1.9.0 pycodestyle-2.6.0 pydocstyle-5.1.1 pyflakes-2.2.0 pyparsing-2.4.7 pytest-6.0.2 regex-2020.9.27 six-1.15.0 snowballstemmer-2.0.0 testfixtures-6.14.2 toml-0.10.1 typed-ast-1.4.1
Removing intermediate container f4743afd3a31
 ---> c63db68e69d5
Step 15/15 : CMD ["flask", "run"]
 ---> Running in c0f90d383fb2
Removing intermediate container c0f90d383fb2
 ---> 8552c5d064ca

Successfully built 8552c5d064ca
Successfully tagged site-development:latest
Recreating mysite_flask-dev_1 ... 
stephen@stephen:~/Projects/mysite$ docker-compose ps
docker-compose ps
       Name           Command    State           Ports         
---------------------------------------------------------------
mysite_flask-dev_1   flask run   Up      0.0.0.0:5000->5000/tcp
stephen@stephen:~/Projects/mysite$ docker-compose logs
docker-compose logs
Attaching to mysite_flask-dev_1
flask-dev_1  |  * Tip: There are .env or .flaskenv files present. Do "pip install python-dotenv" to use them.
flask-dev_1  |  * Serving Flask app "mysite" (lazy loading)
flask-dev_1  |  * Environment: development
flask-dev_1  |  * Debug mode: on
flask-dev_1  |  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
flask-dev_1  |  * Restarting with stat
flask-dev_1  |  * Tip: There are .env or .flaskenv files present. Do "pip install python-dotenv" to use them.
flask-dev_1  |  * Debugger is active!
flask-dev_1  |  * Debugger PIN: 124-299-806
sat1017
  • 333
  • 1
  • 4
  • 10
  • Have you tried adding `EXPOSE 5000` to your Dockerfile? See: https://docs.docker.com/engine/reference/builder/#expose – Robert Nubel Oct 06 '20 at 03:54
  • 1
    @RobertNubel yes. I actually had that command in there but deleted it. Docker-compose ports exposes and publishes the ports. At least that is what I understood from the documentation. – sat1017 Oct 06 '20 at 03:55
  • Right, though it might be helpful to run just the container to determine if it's a compose issue or not. Looking at the docker compose quick start guide, though, the example app happens to be a Flask app and the only difference I can really see is that they're setting `ENV FLASK_RUN_HOST=0.0.0.0`, which might help Flask listen correctly. – Robert Nubel Oct 06 '20 at 04:05
  • @RobertNubel yea o was using that guide too. I wanted to keep as much as I could in the compose file which is why I deleted the expose command. I didn’t notice the env variable so I’ll take a look at that. To be honest idk the equivalent docket run commands, I only now how to use socket-compose. It seems like a lot more verbose of commands to use run to get the ports mapped etc so I didn’t want to debug that way unless I had to. Was hoping someone could point at on obvious bug – sat1017 Oct 06 '20 at 04:08
  • @RobertNubel well sir you have done it. I needed the FLASK_RUN_HOSt env. Now time to figure out what it does. I set the host machine to 0.0.0.0:5000 in the .yml ports mapping so not sure what the difference is. – sat1017 Oct 06 '20 at 04:36
  • 1
    So Flask needs to be told to listen on 0.0.0.0 specifically, because then it listens on every network interface and not just the loopback (see: https://stackoverflow.com/questions/20778771/what-is-the-difference-between-0-0-0-0-127-0-0-1-and-localhost) -- so, binding it to 127.0.0.1 would work on your bare metal, but not in a VM or docker container. The port mapping change you tried, though, was I believe mapping port 5000 bound to your *host's* 0.0.0.0, and wasn't affecting the container at all. – Robert Nubel Oct 06 '20 at 04:42

1 Answers1

0

Per docker quickstart guide you need to set the ENV FLASK_RUN_HOST=0.0.0.0 in the Dockerfile.

Moved @robert's helpful comment to an answer

"So Flask needs to be told to listen on 0.0.0.0 specifically because then it listens on every network interface and not just the loopback (see: stackoverflow.com/questions/20778771/…) -- so, binding it to 127.0.0.1 would work on your bare metal, but not in a VM or docker container. The port mapping change you tried, though, was I believe mapping port 5000 bound to your host's 0.0.0.0, and wasn't affecting the container at all."

sat1017
  • 333
  • 1
  • 4
  • 10