简体   繁体   中英

How to access Django Docker app in a Virtual Machine?

Currently, I'm trying to access a simple Django application, which I created in an Azure Virtual Machine. As the application is still simple, I only want to access the "The install worked successfully! Congratulations!" page from my local machine by accessing http://VM_IP:PORT/ . I was able to do just that, but when I tried to Dockerize the project and access the built image from my local machine, it didn't work .

I've already made some setup in my Azure portal so that the Virtual Machine is able to listen to a specific port; in this case is 8080 (so http://VM_IP:8080/ ). I'm quite new to Docker, so I'm assuming there was something missing in the Dockerfile I've created for the project.

Dockerfile

RUN mkdir /app
WORKDIR /app

# Add current directory code to working directory
ADD . /app/

# set default environment variables
ENV PYTHONUNBUFFERED 1
ENV LANG C.UTF-8
ENV DEBIAN_FRONTEND=noninteractive

# set project environment variables
# grab these via Python's os.environ# these are 100% optional here
ENV PORT=8080
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
        tzdata \
        python3-setuptools \
        python3-pip \        python3-dev \
        python3-venv \
        git \
        && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# install environment dependencies
RUN pip3 install --upgrade pip
RUN pip3 install pipenv

# Install project dependencies
RUN pipenv install --skip-lock --system --dev

EXPOSE 8888
CMD gunicorn simple_project.wsgi:application --bind 0.0.0.0:$PORT

I'm not sure what's happening. It will be very appreciated if someone could point out what I was missing? Thanks in advance.

I suspect the problem may be that you're confusing the EXPOSE build-time instruction with the publish runtime flag. Without the latter, any containers on your VM would be inaccessible to the host machine.

Some background:

The EXPOSE instruction is best thought of as documentation; it has no effect on container networking . From the docs :

The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published.

Seems kind of odd at first glance, but it's for good reason: the image itself does not have the permissions to declare host port-mappings — that's up to the container runtime and whoever is operating it (you!).

The way to do this is by passing the --publish or -p flag to the docker run command, allowing you to define a mapping between the port open in the container network and a port on the host machine. So, for example, if I wanted to run an nginx container that can be accessed at port 8080 on my localhost, I'd run: docker run --rm -d -p 8080:80 nginx . The running container is then accessible at localhost:8080 on the host. Of course, you can also use this to expose container ports from one host to another. Without this, any networking configuration in your Dockerfile is executed in the context of the container network, and is basically inaccessible to the host.

TL;DR: you probably just need to publish your ports when you create and run the container on your VM: docker run -p {vm_host_port}:{container_port} {image_name} . Note that port mappings cannot be added or changed for existing containers; you'd have to destroy the container and recreate it.


Side note: while docker run is quick and easy, it can quickly become unmanageable as your project grows and you add in environment variables, attach volumes, define inter-container dependencies, etc. An alternative with native support is docker-compose , which lets you define the runtime configuration of your container (or containers) declaratively in YAML — basically picking up where the Dockerfile leaves off. And once it's set up, you can just run docker-compose up , instead of having to type out lengthy docker commands, and waste time debugging when you forgot to include a flag, etc. Just like we use Dockerfile s to have a declarative, version-controlled description of how to build our image, I like to think of docker-compose as one way to create a declarative, version-controlled description for how to run and orchestrate our image(s).


Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM