I'd recommend using an ordinary Python virtual environment here. This uses tooling built into the standard Python distribution (so it's available on almost every Unix-like host; Docker would be an additional installation) and doesn't require administrator-level permissions. Since this uses the host filesystem normally, you don't need to copy files around, manually map directories, worry about wrong-architecture native libraries, and so on.
VENV := venv
# Create the virtual environment
$(VENV)/bin/python3:
python3 -m venv "$(VENV)"
# Any application stub installed by a package
$(VENV)/bin/pytest: requirements.txt $(VENV)/bin/python3
"$(VENV)/bin/pip" install -r "$<"
# Run the tests
.PHONY: test
test: $(VENV)/bin/pytest
"$(VENV)/bin/python3" ./py_code/run_tests.py
If you need to build a Docker image, it generally should be self-contained. Do not bind-mount or docker cp the code into the image; COPY it in, so that it can be docker run without also having a copy of the source code separately. You can then docker run an alternate command, without needing the docker exec debugging tool.
REGISTRY := docker.io
IMAGE := me/regex-locator
TAG := latest
DOCKER_IMAGE := $(REGISTRY)/$(IMAGE):$(TAG)
.PHONY: docker-build docker-push docker-run docker-test
docker-build: .docker-build
.docker-build: Dockerfile requirements.txt app/main.py ...
docker build -t "$(DOCKER_IMAGE)" .
touch "$@"
docker-push: docker-build
docker push "$(DOCKER_IMAGE)"
docker-run: docker-build
docker run --rm -p 8000:8000 "$(DOCKER_IMAGE)"
docker-test: docker-build
docker run --rm "$(DOCKER_IMAGE)" ./proj/run_tests.py
This requires you to make sure your image actually is self-contained -- it shouldn't be an empty shell that could eventually run something.
FROM python:3.7.1
WORKDIR /regex_locator
COPY ./py_code/req.txt . # no particular need for a subdirectory
RUN pip install -r req.txt
COPY ./py_code . # make sure to copy the rest of the application too
CMD ./main.py # and set a useful command for the container to run
Your unit tests shouldn't have complex dependencies. (Use an in-memory database like SQLite or mock other dependencies: tests that are 80% functional and 100% easy to run are much better than tests that are 100% functional but very hard to run.) It shouldn't make a different whether they run in the container or in a virtual environment. In that case you can run unit tests on the host, and if they pass, build and publish your image.
make test # in a virtual environment
make docker-push # building the image along the way