如何在葡萄酒仿真的python版本中在Docker容器内部正确安装和运行pip?

问题描述

我想用Python做一个MetaTrader5环境。虽然我可以在Windows机器上做到这一点,但我想将其作为独立的Docker容器部署在我的(我还有两个我更喜欢编码的系统:mac和linux)机器或AWS中ECR。

为此,我创建了这个docker文件

FROM ubuntu:20.04

# In order to use the python version,we'll have to install
# wine emulator. We're installing both 32 and 64 bits API.
RUN dpkg --add-architecture i386
RUN apt update
ENV TZ=UTC
RUN apt-get install --assume-yes apt-utils
RUN DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes tzdata
RUN apt-get install --assume-yes wine64 wine32

# The root wine prefix will be: /root/.wine.

# Now MetaTrader5 is being moved to the Program Files directory.
copY ["MetaTrader5","/root/.wine/drive_c/Program Files/MetaTrader5"]

# Also the Python interpreter is moved to that directory.
ADD ["python-3.9.0","/root/.wine/drive_c/Program Files/python-3.9.0"]

# And the get-pip script is added to the standard interpreter.
ADD ["https://bootstrap.pypa.io/get-pip.py","/root/.wine/drive_c/Program Files/python-3.9.0/get-pip.py"]

# The server script itself is then added as another application.
RUN ["mkdir","-p","/root/.wine/drive_c/Program Files/MetaTrader5 AI Server"]
copY ["server.py","/root/.wine/drive_c/Program Files/MetaTrader5 AI Server/server.py"]

############### 'Till this point,everything is fine.

# Now,pip will be installed for windows.
RUN ["wine","/root/.wine/drive_c/Program Files/python-3.9.0/pythonw.exe","/root/.wine/drive_c/Program Files/python-3.9.0/get-pip.py"]

# And then,MetaTrader will be installed,along with aiohttp
# library for websockets.
# RUN pip install MetaTrader5 aiohttp

# Choosing this tail command is just for debug
# purposes,as the true implementation will use
# the server.py file as entry point.
CMD ["tail","-f","/dev/null"]

我遇到的问题涉及最后一部分:执行get-pip.py时,将使用Scripts/和{{1来创建/root/.wine/drive_c/Program Files/python-3.9.0/Scripts目录(pip.exe) }}可执行文件,但是在尝试调用它们中的任何一个时,都会出现错误,因为似乎未安装easy_install.exe python模块

这可以通过运行以下dockerfile进行测试:

pip

然后:

$ docker build . --tag=mt5pyserver
$ docker run --name=prueba -it mt5pyserver bash

我需要在Windows python解释器中正确安装root@a169a4c4aae8:~# cd ".wine/drive_c/Program Files/python-3.9.0" root@a169a4c4aae8:~/.wine/drive_c/Program Files/python-3.9.0# wine python.exe get-pip.py Collecting pip Using cached pip-20.2.3-py2.py3-none-any.whl (1.5 MB) Collecting setuptools Using cached setuptools-50.3.0-py3-none-any.whl (785 kB) Collecting wheel Using cached wheel-0.35.1-py2.py3-none-any.whl (33 kB) Installing collected packages: pip,setuptools,wheel WARNING: The scripts pip.exe,pip3.9.exe and pip3.exe are installed in 'C:\Program Files\python-3.9.0\Scripts' which is not on PATH. Consider adding this directory to PATH or,if you prefer to suppress this warning,use --no-warn-script-location. WARNING: The scripts easy_install-3.9.exe and easy_install.exe are installed in 'C:\Program Files\python-3.9.0\Scripts' which is not on PATH. Consider adding this directory to PATH or,use --no-warn-script-location. WARNING: The script wheel.exe is installed in 'C:\Program Files\python-3.9.0\Scripts' which is not on PATH. Consider adding this directory to PATH or,use --no-warn-script-location. Successfully installed pip-20.2.3 setuptools-50.3.0 wheel-0.35.1 root@a169a4c4aae8:~/.wine/drive_c/Program Files/python-3.9.0# pip bash: pip: command not found root@a169a4c4aae8:~/.wine/drive_c/Program Files/python-3.9.0# wine Scripts/pip.exe Traceback (most recent call last): File "runpy.py",line 197,in _run_module_as_main File "runpy.py",line 87,in _run_code File "C:\Program Files\python-3.9.0\Scripts\pip.exe\__main__.py",line 4,in <module> ModuleNotFoundError: No module named 'pip' root@a169a4c4aae8:~/.wine/drive_c/Program Files/python-3.9.0# wine --version wine-5.0 (Ubuntu 5.0-3ubuntu1) root@a169a4c4aae8:~/.wine/drive_c/Program Files/python-3.9.0# root@a169a4c4aae8:~/.wine/drive_c/Program Files/python-3.9.0# wine Scripts/pip.exe Traceback (most recent call last): File "runpy.py",in <module> ModuleNotFoundError: No module named 'pip' root@a169a4c4aae8:~/.wine/drive_c/Program Files/python-3.9.0# 。有一个根本原因:软件包pip仅对于Windows python版本存在。最后,我想安装该软件包以及aiohttp。然后,服务器将使用MetaTrader5 documentation for Python integration中所述的那些软件包以及我自己的一些魔法。

我该怎么做才能避免出现该错误

解决方法

看看this Dockerfile。它可能会给您一些见识。所使用的方法完全不同。

Dockerfile与您的设置之间存在一些值得注意的区别:

  • 使用 WineHQ 的软件包存储库中的wine,而不是Ubuntu的软件包存储库。
  • python.org下载python msi设置文件,并使用wine msiexec安装它们。

这里是Dockerfile中的一个例外:

...
...

ARG PYINSTALLER_VERSION=4.0

...
...

RUN set -x \
    && for msifile in `echo core dev exe lib path pip tcltk tools`; do \
        wget -nv "https://www.python.org/ftp/python/$PYTHON_VERSION/amd64/${msifile}.msi"; \
        wine msiexec /i "${msifile}.msi" /qb TARGETDIR=C:/Python37; \
        rm ${msifile}.msi; \
    done \
    && cd /wine/drive_c/Python37 \
    && echo 'wine '\''C:\Python37\python.exe'\'' "$@"' > /usr/bin/python \
    && echo 'wine '\''C:\Python37\Scripts\easy_install.exe'\'' "$@"' > /usr/bin/easy_install \
    && echo 'wine '\''C:\Python37\Scripts\pip.exe'\'' "$@"' > /usr/bin/pip \
    && echo 'wine '\''C:\Python37\Scripts\pyinstaller.exe'\'' "$@"' > /usr/bin/pyinstaller \
    && echo 'wine '\''C:\Python37\Scripts\pyupdater.exe'\'' "$@"' > /usr/bin/pyupdater \
    && echo 'assoc .py=PythonScript' | wine cmd \
    && echo 'ftype PythonScript=c:\Python37\python.exe "%1" %*' | wine cmd \
    && while pgrep wineserver >/dev/null; do echo "Waiting for wineserver"; sleep 1; done \
    && chmod +x /usr/bin/python /usr/bin/easy_install /usr/bin/pip /usr/bin/pyinstaller /usr/bin/pyupdater \
    && (pip install -U pip || true) \
    && rm -rf /tmp/.wine-*

ENV W_DRIVE_C=/wine/drive_c
ENV W_WINDIR_UNIX="$W_DRIVE_C/windows"
ENV W_SYSTEM64_DLLS="$W_WINDIR_UNIX/system32"
ENV W_TMP="$W_DRIVE_C/windows/temp/_$0"

# install Microsoft Visual C++ Redistributable for Visual Studio 2015,2017 and 2019 dll files
RUN set -x \
    && rm -f "$W_TMP"/* \
    && wget -P "$W_TMP" https://aka.ms/vs/16/release/vc_redist.x64.exe \
    && cabextract -q --directory="$W_TMP" "$W_TMP"/vc_redist.x64.exe \
    && cabextract -q --directory="$W_TMP" "$W_TMP/a10" \
    && cabextract -q --directory="$W_TMP" "$W_TMP/a11" \
    && cd "$W_TMP" \
    && rename 's/_/\-/g' *.dll \
    && cp "$W_TMP"/*.dll "$W_SYSTEM64_DLLS"/

# install pyinstaller
RUN /usr/bin/pip install pyinstaller==$PYINSTALLER_VERSION

...
...

此外,为什么在Python 2> = 2.7.9或Python 3> = 3.4 already includes pip时必须安装pip

还要注意recommended是在同一apt-get update/install步骤中放置相关命令(RUN)。