Reputation: 63
I'm experiencing differences with the contents of a container depending on whether I open a bash shell via docker run -i -t <container> bash
or docker-compose run <container> bash
and I don't know/understand how this is possible.
To aid in the explanation, please see this screenshot from my terminal. In both instances, I am running the image called blaze
which has been built from the Dockerfile
in my code. One of the steps during the build is to create a virutalenv called venv
, however when I open a bash shell via docker-compose
this virtualenv doesn't seem to exist unlike when I run docker run ...
.
I am relatively new to setting up my own builds with Docker, but surely if they are both referencing the same image, the output of ls
within a bash shell should be the same? I would greatly appreciate any help or guidance to resources that would explain what exactly is going wrong here...
As an additional point, running docker images shows that both commands must be using the same image...
Thanks in advance!
This is my Dockerfile
:
FROM blaze-base-image:latest
# add an URL that PIP automatically searches (e.g., Azure Artifact Store URL)
ARG INDEX_URL
ENV PIP_EXTRA_INDEX_URL=$INDEX_URL
# Copy source code to docker image
RUN mkdir /opt/app
COPY . /opt/app
RUN ls /opt/app
# Install Blaze pip dependencies
WORKDIR /opt/app
RUN python3.7 -m venv /opt/app/venv
RUN /opt/app/venv/bin/python -m pip install --upgrade pip
RUN /opt/app/venv/bin/python -m pip install keyring artifacts-keyring
RUN touch /opt/app/venv/pip.conf
RUN echo $'[global]\nextra-index-url=https://www.index.com' > /opt/app/venv/pip.conf
RUN /opt/app/venv/bin/python -m pip install -r /opt/app/requirements.txt
RUN /opt/app/venv/bin/python -m spacy download en_core_web_sm
# Comment
CMD ["echo", "Container build complete"]
And this is my docker-compose.yml
:
version: '3'
services:
blaze:
build: .
image: blaze
volumes:
- .:/opt/app
Upvotes: 0
Views: 93
Reputation: 158748
There are two intersecting things going on here:
When you have a Compose volumes:
or docker run -v
option mounting host content over a container directory, the host content completely replaces what's in the image. If you don't have a ./venv
directory on the host, then there won't be a /opt/app/venv
directory in the container. That's why, when you docker-compose run blaze ...
, the virtual environment is missing.
If you docker run
a container, the only options that are considered are those in that specific docker run
command. docker run
doesn't know about the docker-compose.yml
file and won't take options from there. That means there isn't this volume mount in the docker run
case, which is why the virtual environment reappears.
Typically in Docker you don't need a virtual environment at all: the Docker image is isolated from other images and Python installations, and so it's safe and normal to install your application into the "system" Python. You also typically want your image to be self-contained and not depend on content from the host, so you wouldn't generally need the bind mount you show.
That would simplify your Dockerfile to:
FROM blaze-base-image:latest
# Any ARG will automatically appear as an environment variable to
# RUN directives; this won't be needed at run time
ARG PIP_EXTRA_INDEX_URL
# Creates the directory if it doesn't exist
WORKDIR /opt/app
# Install the Python-level dependencies
RUN pip install --upgrade pip
COPY requirements.txt .
RUN pip install -r requirements.txt
# The requirements.txt file should list every required package
# Install the rest of the application
COPY . .
# Set the main container command to run the application
CMD ["./app.py"]
The docker-compose.yml
file can be similarly simplified to
version: '3.8' # '3' means '3.0'
services:
blaze:
build: .
# Compose picks its own image name
# Do not need volumes:, the image is self-contained
and then it will work consistently with either docker run
or docker-compose run
(or docker-compose up
).
Upvotes: 6