pythondockerdockerfilepypipypiserver

Local pypi server tells me 403 Forbidden when registering packages


I am trying to deploy a pypi-server to host our internal packages. I've been pulling my hair out over the behavior of pypi inside this docker container.

Dockerfile

FROM python:3.5

RUN apt-get update
RUN pip install --upgrade pip
RUN pip install -U passlib pypiserver[cache]==1.2.0
RUN mkdir -p /src/pypi/packages

EXPOSE 8080
ADD ./htpasswd /src/pypi/htpasswd

CMD ["pypi-server", "-p 8080", "-P", "/src/pypi/htpasswd","/src/pypi/packages"]

Pretty straightforward, right? Sister to the dockerfile there is of course a file called htpasswd containing a username/password pair.

If I got through the steps defined in the docker file locally (in my environment outside docker) and then execute the command defined above, it works! I can register packages against it.

Pypi running outside Dockerfile:

python setup.py register -r local
running register
running egg_info
writing top-level names to ah_model.egg-info/top_level.txt
writing dependency_links to ah_model.egg-info/dependency_links.txt
writing ah_model.egg-info/PKG-INFO
file foobar_utils.py (for module foobar_utils) not found
reading manifest file 'ah_model.egg-info/SOURCES.txt'
writing manifest file 'ah_model.egg-info/SOURCES.txt'
running check
Registering ah_model to http://localhost:8081
Server response (200): OK

However, if I build and run the dockerfile, then try to register inside that, it does NOT work:

Pypi running inside docker:

python setup.py register -r local
running register
running egg_info
writing top-level names to ah_model.egg-info/top_level.txt
writing ah_model.egg-info/PKG-INFO
writing dependency_links to ah_model.egg-info/dependency_links.txt
file foobar_utils.py (for module foobar_utils) not found
reading manifest file 'ah_model.egg-info/SOURCES.txt'
writing manifest file 'ah_model.egg-info/SOURCES.txt'
running check
Registering ah_model to http://localhost:8080
Server response (403): Forbidden

Is there something about the way pypi works that requires special tweaking for being inside a docker container? Has anyone tried this themselves?

UPDATE

Looks like the docker container is listening on port 8080:

root@a0ec19c89a9d:/src/pypi# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1/python3.5  

Solution

  • Expose does not expose the ports to the host machine. To do that you need to use -p or -P or create a docker-compose.yml file with ports definitions.

    See https://docs.docker.com/engine/reference/builder/#expose and https://docs.docker.com/compose/compose-file/#ports