├── .gitignore ├── devpi-client ├── docker-compose.yml.example ├── Dockerfile ├── devpi-requirements.txt ├── LICENSE.md ├── README.md └── entrypoint.sh /.gitignore: -------------------------------------------------------------------------------- 1 | docker-compose.yml 2 | -------------------------------------------------------------------------------- /devpi-client: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | devpi use http://localhost:3141 > /dev/null 2>&1 5 | devpi login root --password=$(cat "$DEVPI_SERVER_ROOT/.root_password") 6 | 7 | if [ "${1:-}" == "bash" ]; then 8 | exec "$@" 9 | fi 10 | exec devpi "$@" 11 | -------------------------------------------------------------------------------- /docker-compose.yml.example: -------------------------------------------------------------------------------- 1 | version: '2.0' 2 | 3 | services: 4 | devpi-server: 5 | image: lordgaav/devpi:latest 6 | ports: 7 | - 3141:3141 8 | volumes: 9 | - /some/place:/devpi 10 | - /path/to/ldap.yml:/ldap.yml 11 | command: 12 | - --ldap-config=/ldap.yml 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9 2 | 3 | # Install devpi and dependencies 4 | COPY devpi-requirements.txt / 5 | RUN pip install -r /devpi-requirements.txt 6 | 7 | # Set default server root 8 | ENV DEVPI_SERVER_ROOT=/devpi 9 | 10 | # Add entrypoint 11 | COPY devpi-client /usr/local/bin/ 12 | COPY entrypoint.sh / 13 | ENTRYPOINT [ "/bin/bash", "/entrypoint.sh" ] 14 | EXPOSE 3141 15 | -------------------------------------------------------------------------------- /devpi-requirements.txt: -------------------------------------------------------------------------------- 1 | # Main server and web views 2 | devpi-server==6.3.1 3 | devpi-client==5.2.3 4 | devpi-web==4.0.8 5 | 6 | # Web extensions 7 | devpi-findlinks==2.0.1 8 | devpi-lockdown==2.0.0 9 | devpi-json-info==0.1.3 10 | 11 | # Tools 12 | devpi-cleaner==0.3.0 13 | git+https://github.com/max-arnold/devpi-slack.git@eb598f705b918705c8fc6620773f6ed5c5e57e94 # 0.1.4 14 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Nick Douma 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Docker image for devpi 2 | ====================== 3 | A ready to use Docker image for [devpi](http://doc.devpi.net/latest/). It includes 4 | the following plugins and components: 5 | 6 | * devpi-server, devpi-web and devpi-client 7 | * [devpi-findlinks](https://pypi.python.org/pypi/devpi-findlinks) 8 | * [devpi-cleaner](https://pypi.python.org/pypi/devpi-cleaner) 9 | * [devpi-slack](https://pypi.python.org/pypi/devpi-slack) 10 | * [devpi-lockdown](https://pypi.python.org/pypi/devpi-lockdown) 11 | * [devpi-json](https://pypi.org/project/devpi-json-info/) 12 | 13 | Starting the image 14 | ------------------ 15 | `devpi` needs its own folder to store packages and data, which you probably want 16 | to map a volume to. Additionally, map TCP port 3141. 17 | 18 | ```bash 19 | docker run -d -p 3141:3141 -v /some/place:/devpi \ 20 | --name devpi-server lordgaav/devpi:latest 21 | ``` 22 | 23 | The first time it runs, the startup script will generate a password for the root 24 | user and store it in `.root_password` in the volume. 25 | 26 | If you want to use the LDAP plugin, you need to map the YAML configuration file 27 | into the Docker and tell `devpi-server` to use it: 28 | 29 | ```bash 30 | docker run -d -p 3141:3141 -v /some/place:/devpi -v /path/to/ldap.yml:/ldap.yml \ 31 | --name devpi-server lordgaav/devpi:latest --ldap-config=/ldap.yml 32 | ``` 33 | 34 | 35 | devpi-client helper 36 | ------------------- 37 | A small helper script is provided to manipulate the running container. The 38 | script will automatically log in as the `root` user for running commands. 39 | 40 | ```bash 41 | $ docker exec -it devpi-server devpi-client -h 42 | logged in 'root', credentials valid for 10.00 hours 43 | usage: /usr/local/bin/devpi [-h] [--version] [--debug] [-y] [-v] 44 | [--clientdir DIR] 45 | {quickstart,use,getjson,patchjson,list,remove,user,login,logoff,index,upload,test,push,install,refresh} 46 | ... 47 | ``` 48 | 49 | Alternatively, you can start an interactive shell. 50 | 51 | ```bash 52 | $ docker exec -it devpi-server devpi-client bash 53 | logged in 'root', credentials valid for 10.00 hours 54 | root@c4fa8a7b14cf:/# 55 | ``` 56 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | function generate_password() { 6 | # We disable exit on error because we close the pipe 7 | # when we have enough characters, which results in a 8 | # non-zero exit status 9 | set +e 10 | tr -cd '[:alnum:]' < /dev/urandom | fold -w30 | head -n1 | tr -cd '[:alnum:]' 11 | set -e 12 | } 13 | 14 | function kill_devpi() { 15 | _PID=$(pgrep devpi-server) 16 | echo "ENTRYPOINT: Sending SIGTERM to PID $_PID" 17 | kill -SIGTERM "$_PID" 18 | } 19 | 20 | if [ "${1:-}" == "bash" ]; then 21 | exec "$@" 22 | fi 23 | 24 | DEVPI_ROOT_PASSWORD="${DEVPI_ROOT_PASSWORD:-}" 25 | if [ -f "$DEVPI_SERVER_ROOT/.root_password" ]; then 26 | DEVPI_ROOT_PASSWORD=$(cat "$DEVPI_SERVER_ROOT/.root_password") 27 | elif [ -z "$DEVPI_ROOT_PASSWORD" ]; then 28 | DEVPI_ROOT_PASSWORD=$(generate_password) 29 | fi 30 | 31 | if [ ! -d "$DEVPI_SERVER_ROOT" ]; then 32 | echo "ENTRYPOINT: Creating devpi-server root" 33 | mkdir -p "$DEVPI_SERVER_ROOT" 34 | fi 35 | 36 | initialize=no 37 | if [ ! -f "$DEVPI_SERVER_ROOT/.serverversion" ]; then 38 | initialize=yes 39 | echo "ENTRYPOINT: Initializing server root $DEVPI_SERVER_ROOT" 40 | devpi-init --serverdir "$DEVPI_SERVER_ROOT" 41 | fi 42 | 43 | echo "ENTRYPOINT: Starting devpi-server" 44 | devpi-server --host 0.0.0.0 --port 3141 --serverdir "$DEVPI_SERVER_ROOT" "$@" & 45 | 46 | timeout 10 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' localhost 3141 47 | 48 | echo "ENTRYPOINT: Installing signal traps" 49 | trap kill_devpi SIGINT SIGTERM 50 | 51 | if [ "$initialize" == "yes" ]; then 52 | echo "ENTRYPOINT: Initializing devpi-server" 53 | devpi use http://localhost:3141 54 | devpi login root --password='' 55 | echo "ENTRYPOINT: Setting root password to $DEVPI_ROOT_PASSWORD" 56 | devpi user -m root "password=$DEVPI_ROOT_PASSWORD" 57 | echo -n "$DEVPI_ROOT_PASSWORD" > "$DEVPI_SERVER_ROOT/.root_password" 58 | devpi logoff 59 | fi 60 | 61 | echo "ENTRYPOINT: Watching devpi-server" 62 | PID=$(pgrep devpi-server) 63 | 64 | if [ -z "$PID" ]; then 65 | echo "ENTRYPOINT: Could not determine PID of devpi-server!" 66 | exit 1 67 | fi 68 | 69 | set +e 70 | 71 | while : ; do 72 | kill -0 "$PID" > /dev/null 2>&1 || break 73 | sleep 2s 74 | done 75 | 76 | echo "ENTRYPOINT: devpi-server died, exiting..." 77 | --------------------------------------------------------------------------------