使用Docker处理Python本地开发中的M1问题的方法

390 阅读2分钟

我有一台新的笔记本电脑。一台带M1处理器的MacbookPro。电池性能令人印象深刻,性能非常好,但并非都是好东西。M1处理器有一个不同的架构。现在我们使用arm64而不是x86_64。

问题是当我们需要编译的时候。我们需要考虑到这一点。对于python,我通常使用pyenv来管理我笔记本电脑中不同的python版本,我为每个项目创建一个virtualenv来隔离我的环境。它工作得很好,但现在我面临着由于M1架构带来的问题。例如,为了用pyenv安装一个特定的python版本,我需要对它进行编译。另外,当我安装一个pip包并且它提供了一个二进制文件时,它必须是可用的M1版本。

这种问题有点让人沮丧。苹果公司为我们提供了rosetta来使用x86二进制文件,但简单的pip安装xxx却变成了一场噩梦。对我来说,这是不可能的。我想把项目部署到生产中,而不是成为一个低级架构的专家。所以,Docker是我的朋友。

我的解决方案是用Docker来避免这种问题。现在我没有使用pyenv。如果我需要一个python解释器,我会建立一个Docker镜像。我不使用virtualenv,而是创建一个容器。

PyCharm也允许我使用docker解释器,没有任何问题。

这就是我的python Dockerfile。

FROM python:3.9.6 AS base

ENV APP_HOME=/src
ENV APP_USER=appuser

RUN groupadd -r $APP_USER && \
    useradd -r -g $APP_USER -d $APP_HOME -s /sbin/nologin -c "Docker image user" $APP_USER

WORKDIR $APP_HOME

ENV TZ 'Europe/Madrid'
RUN echo $TZ > /etc/timezone && \
apt-get update && apt-get install --no-install-recommends \
    -y tzdata && \
    rm /etc/localtime && \
    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
    dpkg-reconfigure -f noninteractive tzdata && \
    apt-get clean

RUN pip install --upgrade pip

FROM base

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

WORKDIR $APP_HOME

COPY requirements.txt .
RUN pip install -r requirements.txt

ADD src .

RUN chown -R $APP_USER:$APP_USER $APP_HOME

USER $APP_USER

我可以建立我的容器。

docker build -t demo .

现在我可以在pycharm中使用我的demo:最新镜像添加解释器了。

如果我需要添加一个pip依赖项,我不能用pip安装在本地来完成。我有两个选择。在requirements.txt中添加依赖项,然后重新构建镜像,或者在docker容器中运行pip("用docker run -it -rm ...")。为了组织这些脚本,我们可以轻松地创建一个package.json文件。

{
  "name": "flaskdemo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "docker_local_build": "docker build -t $npm_package_name .",
    "freeze": "docker run -it --rm -v \"$PWD\"/src:/src $npm_package_name python -m pip freeze > requirements.txt",
    "local": "npm run docker_local_build && npm run freeze",
    "python": "docker run -it --rm -v $PWD/src:/src $npm_package_name:latest",
    "bash": "docker run -it --rm -v $PWD/src:/src $npm_package_name:latest bash"
  },
  "author": {
    "name": "Gonzalo Ayuso",
    "email": "gonzalo123@gmail.com",
    "url": "https://gonzalo123.com"
  },
  "license": "MIT"
}

题外话

M1还有一个问题。也许你不需要面对这个问题,但如果你用M1笔记本构建了一个docker容器,并试图将这个容器部署到linux服务器上(不是arm64服务器),你的容器就无法工作。为了解决这个问题,你需要用正确的架构来构建你的容器。Docker允许我们这样做。比如说:

docker buildx build --platform linux/amd64 -t gonzalo123/demo:prodution .

github.com/gonzalo123/…