使用docker ENTRYPOINT脚本激活virtualenv时出错



我正试图在Windows10上使用virtualenv设置构建一个简单的Django-Docker容器。图像本身已经成功构建,但是当我尝试使用入口点脚本启动容器时,我遇到了一个奇怪的错误,即找不到我的virtualenv文件。

请注意,在我决定添加virtualenv部分之前,容器运行得非常好(根据Dockerfile中的TODO注释(。容器UP并且正在运行。

有人能分享他们对为什么会发生这种情况的想法吗?请注意,这是我的第一张高山照片。

PS。我使用PyCharm作为我的IDE,并且我已将所有行分隔符更改为LF

D:CodeProjectsTest_virtualenv_Dockerfiles>docker-compose ps
Name                  Command               State    Ports
-------------------------------------------------------------
django_test   /venv-entrypoint.sh sh -c  ...   Exit 2

docker compose.yml

version: '3.2'
web:
build:
context: .
dockerfile: Deploy/Django/Dockerfile
image: django_test
container_name: django_test
volumes:
- .:/app_server
ports:
- "9000:8000"
tty: true
command: >
sh -c "python manage.py runserver 0.0.0.0:8000"

Dockerfile

FROM python:3.8-alpine
MAINTAINER cBeTyLkaTa
# Setup environment variables
ENV PYTHONUNBUFFERED=1 
RUN_USER=www-data 
ENV_DIR=/app_server 
VIRTUALENV_DIR=/app_server/venv 
BIN_DIR=/app_server/venv/bin 
HOME_DIR=/var/www
# Create new run user
RUN adduser -D $RUN_USER
# Setup work directory
RUN mkdir $ENV_DIR $HOME_DIR
WORKDIR $ENV_DIR

# Install packages
# NB. Adding bash as Alpine images do not have installed by default (otherwise use `ash` to login)
RUN apk add --no-cache --update bash
RUN apk update && 
apk add make 
curl 
vim 
git
# Setup virtual environment and install requirements/dependencies
COPY requirements.txt $ENV_DIR/requirements.txt
RUN pip install virtualenv
RUN virtualenv -p python venv
RUN $BIN_DIR/pip install -r $ENV_DIR/requirements.txt
COPY . $ENV_DIR
EXPOSE 9000
# TODO add entrypoint to activate the virtual environment
COPY Deploy/Django/venv-entrypoint.sh /
RUN chmod a+x /venv-entrypoint.sh
# Change file permission for the new run user and switch to that user
#RUN chown -R $RUN_USER:$RUN_USER $ENV_DIR $HOME_DIR /venv-entrypoint.sh
ENTRYPOINT ["/venv-entrypoint.sh"]

venv入口点.sh

#!/bin/sh
source /app_server/venv/bin/activate
exec "$@"

生成输出

Building web
Step 1/17 : FROM python:3.8-alpine
---> 6c32e2504283
Step 2/17 : MAINTAINER cBeTyLkaTa
---> Running in 15a8c54f6108
Removing intermediate container 15a8c54f6108
---> 193086010346
Step 3/17 : ENV PYTHONUNBUFFERED=1     RUN_USER=www-data     ENV_DIR=/app_server     VIRTUALENV_DIR=/app_server/venv     BIN_DIR=/app_server/venv/bin     HOME_DIR=/var/www
---> Running in 58d3674079a0
Removing intermediate container 58d3674079a0
---> e6d90a27efe8
Step 4/17 : RUN adduser -D $RUN_USER
---> Running in d126a2f85982
Removing intermediate container d126a2f85982
---> 934ff481f5c8
Step 5/17 : RUN mkdir $ENV_DIR $HOME_DIR
---> Running in 896b80dcd473
Removing intermediate container 896b80dcd473
---> 529d46ca0266
Step 6/17 : WORKDIR $ENV_DIR
---> Running in a452c441afd4
Removing intermediate container a452c441afd4
---> d1d30ed270b0
Step 7/17 : RUN apk add --no-cache --update bash
---> Running in d71f7a25654f
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
(1/1) Installing bash (5.0.11-r1)
Executing bash-5.0.11-r1.post-install
Executing busybox-1.31.1-r9.trigger
OK: 12 MiB in 35 packages
Removing intermediate container d71f7a25654f
---> c26f3c97b47d
Step 8/17 : RUN apk update &&     apk add make     curl     vim     git
---> Running in a8fe50461a39
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
v3.11.6-22-g595722b8fb [http://dl-cdn.alpinelinux.org/alpine/v3.11/main]
v3.11.6-26-ga2d911e64f [http://dl-cdn.alpinelinux.org/alpine/v3.11/community]
OK: 11273 distinct packages available
(1/9) Installing nghttp2-libs (1.40.0-r0)
(2/9) Installing libcurl (7.67.0-r0)
(3/9) Installing curl (7.67.0-r0)
(4/9) Installing pcre2 (10.34-r1)
(5/9) Installing git (2.24.3-r0)
(6/9) Installing make (4.2.1-r2)
(7/9) Installing xxd (8.2.0-r0)
(8/9) Installing lua5.3-libs (5.3.5-r2)
(9/9) Installing vim (8.2.0-r0)
Executing busybox-1.31.1-r9.trigger
OK: 57 MiB in 44 packages
Removing intermediate container a8fe50461a39
---> dfec727547a6
Step 9/17 : COPY requirements.txt $ENV_DIR/requirements.txt
---> 8d51b6f66a53
Step 10/17 : RUN pip install virtualenv
---> Running in ce6cad56b303
Collecting virtualenv
Downloading virtualenv-20.0.20-py2.py3-none-any.whl (4.7 MB)
Collecting six<2,>=1.9.0
Downloading six-1.14.0-py2.py3-none-any.whl (10 kB)
Collecting appdirs<2,>=1.4.3
Downloading appdirs-1.4.3-py2.py3-none-any.whl (12 kB)
Collecting filelock<4,>=3.0.0
Downloading filelock-3.0.12-py3-none-any.whl (7.6 kB)
Collecting distlib<1,>=0.3.0
Downloading distlib-0.3.0.zip (571 kB)
Building wheels for collected packages: distlib
Building wheel for distlib (setup.py): started
Building wheel for distlib (setup.py): finished with status 'done'
Created wheel for distlib: filename=distlib-0.3.0-py3-none-any.whl size=340427 sha256=dc12892f48f7abbfcda57326432bf3d45baec7ad7c2f938780ec17362def0e8a
Stored in directory: /root/.cache/pip/wheels/eb/4e/d2/a903d4184fb49e4ac06474d65715b129aee13d69f7d227e78e
Successfully built distlib
Installing collected packages: six, appdirs, filelock, distlib, virtualenv
Successfully installed appdirs-1.4.3 distlib-0.3.0 filelock-3.0.12 six-1.14.0 virtualenv-20.0.20
Removing intermediate container ce6cad56b303
---> 99acb4562180
Step 11/17 : RUN virtualenv -p python venv
---> Running in 7896c112b9a5
created virtual environment CPython3.8.2.final.0-64 in 333ms
creator CPython3Posix(dest=/app_server/venv, clear=False, global=False)
seeder FromAppData(download=False, pip=latest, setuptools=latest, wheel=latest, via=copy, app_data_dir=/root/.local/share/virtualenv/seed-app-data/v1.0.1)
activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
Removing intermediate container 7896c112b9a5
---> ad3985329fd3
Step 12/17 : RUN $BIN_DIR/pip install -r $ENV_DIR/requirements.txt
---> Running in d6ac22e791e3
Collecting Django<3.0,>=2.0
Downloading Django-2.2.12-py3-none-any.whl (7.5 MB)
Collecting sqlparse
Downloading sqlparse-0.3.1-py2.py3-none-any.whl (40 kB)
Collecting pytz
Downloading pytz-2020.1-py2.py3-none-any.whl (510 kB)
Installing collected packages: sqlparse, pytz, Django
Successfully installed Django-2.2.12 pytz-2020.1 sqlparse-0.3.1
Removing intermediate container d6ac22e791e3
---> a69a36022d5b
Step 13/17 : COPY . $ENV_DIR
---> 2b8ab97814c8
Step 14/17 : EXPOSE 9000
---> Running in b54e93640150
Removing intermediate container b54e93640150
---> bec8bf51db4d
Step 15/17 : COPY Deploy/Django/venv-entrypoint.sh /
---> 298bac000732
Step 16/17 : RUN chmod a+x /venv-entrypoint.sh
---> Running in c51d2666deea
Removing intermediate container c51d2666deea
---> 9d1a03413c05
Step 17/17 : ENTRYPOINT ["/venv-entrypoint.sh"]
---> Running in f5cad5c0151a
Removing intermediate container f5cad5c0151a
---> d755701b46d9
Successfully built d755701b46d9
Successfully tagged django_test:latest

码头日志

Attaching to django_test
django_test | /venv-entrypoint.sh: source: line 2: can't open '/app_server/venv/bin/activate': No such file or directory

容器调试:

docker run -it django_test bash
.
.
(venv) /app_server # ls -l
total 28
drwxr-xr-x    4 root     root          4096 May  1 11:15 Deploy
-rwxr-xr-x    1 root     root           819 May  5 14:48 README.md.txt
-rwxr-xr-x    1 root     root             0 May  3 16:35 db.sqlite3
-rwxr-xr-x    1 root     root          1097 May  5 15:50 docker-compose.yml
-rwxr-xr-x    1 root     root           626 May  3 16:35 manage.py
drwxr-xr-x    3 root     root          4096 May  3 16:35 mysite
-rwxr-xr-x    1 root     root            16 May  3 15:52 requirements.txt
drwxr-xr-x    1 root     root          4096 May  5 15:51 venv
(venv) /app_server # ls -l venv/bin/activate
-rw-r--r--    1 root     root          2205 May  5 15:51 venv/bin/activate
(venv) /app_server # ls -la /app_server/venv/bin/
total 88
drwxr-xr-x    1 root     root          4096 May  5 15:51 .
drwxr-xr-x    1 root     root          4096 May  5 15:51 ..
drwxr-xr-x    2 root     root          4096 May  5 15:51 __pycache__
-rw-r--r--    1 root     root          2205 May  5 15:51 activate
-rw-r--r--    1 root     root          1424 May  5 15:51 activate.csh
-rw-r--r--    1 root     root          3055 May  5 15:51 activate.fish
-rw-r--r--    1 root     root          1751 May  5 15:51 activate.ps1
-rw-r--r--    1 root     root          1146 May  5 15:51 activate.xsh
-rw-r--r--    1 root     root          1199 May  5 15:51 activate_this.py
-rwxr-xr-x    1 root     root           274 May  5 15:51 django-admin
-rwxr-xr-x    1 root     root           136 May  5 15:51 django-admin.py
-rwxr-xr-x    1 root     root           241 May  5 15:51 easy_install
-rwxr-xr-x    1 root     root           241 May  5 15:51 easy_install-3.8
-rwxr-xr-x    1 root     root           241 May  5 15:51 easy_install3
-rwxr-xr-x    1 root     root           232 May  5 15:51 pip
-rwxr-xr-x    1 root     root           232 May  5 15:51 pip-3.8
-rwxr-xr-x    1 root     root           232 May  5 15:51 pip3
-rwxr-xr-x    1 root     root           232 May  5 15:51 pip3.8
lrwxrwxrwx    1 root     root            21 May  5 15:51 python -> /usr/local/bin/python
lrwxrwxrwx    1 root     root             6 May  5 15:51 python3 -> python
lrwxrwxrwx    1 root     root             6 May  5 15:51 python3.8 -> python
-rwxr-xr-x    1 root     root           227 May  5 15:51 sqlformat
-rwxr-xr-x    1 root     root           219 May  5 15:51 wheel
-rwxr-xr-x    1 root     root           219 May  5 15:51 wheel-3.8
-rwxr-xr-x    1 root     root           219 May  5 15:51 wheel3
(venv) /app_server # pip -V
pip 20.1 from /app_server/venv/lib/python3.8/site-packages/pip (python 3.8)
(venv) /app_server # which pip
/app_server/venv/bin/pip
(venv) /app_server # which python
/app_server/venv/bin/python
(venv) /app_server/venv/bin $ pip list
Package    Version
---------- -------
Django     2.2.12
pip        20.1
pytz       2020.1
setuptools 46.1.3
sqlparse   0.3.1
wheel      0.34.2

问题在于您的compose-config,它使用主机中的目录覆盖/app_server。只需从docker compose设置中删除卷。

(顺便说一句,我建议不要使用Alpine,它通常会导致Docker构建缓慢:https://pythonspeed.com/articles/alpine-docker-python/)

Docker镜像中通常不需要虚拟环境。映像本身与主机系统隔离,即使将包安装到"系统"Python中,它也将与同一主机上的任何其他Python安装分离。

这让你有一个更简单的Dockerfile:

FROM python:3.8-alpine
ENV PYTHONUNBUFFERED=1
# But don't set environment variables for container paths
# Are bash/curl/make/vim/git actually needed to run the application?
# Or as part of a `pip install` sequence?  Include only if required
WORKDIR /var/www
# Creates the directory for you
# Install Python dependencies into the "system" Python
COPY requirements.txt ./
RUN pip install -r requirements.txt
# Install the rest of the application
COPY . ./
# Runtime metadata
RUN adduser -D www-data
USER www-data
EXPOSE 8000
CMD python manage.py runserver 0.0.0.0:8000

现在,您的代码、标准CMD等都已构建到Dockerfile中,您还可以稍微修剪一下docker-compose.yml

version: '3.2'
services:
web:
build:
context: .
dockerfile: Deploy/Django/Dockerfile
image: django_test
ports:
- "9000:8000"
# do not need container_name:, volumes:, tty:, command:

最新更新