Skip to main content
 首页 » 编程设计

python之使 CMD 对 docker run 产生影响,但对 docker start 没有影响

2025年05月04日41think

背景:

我正在使用 docker 部署 python-web(django) 环境。

我想制作一个干净的docker镜像,只包含运行时环境,但不包含源代码,然后将代码卷进去。

我的 docker 镜像存储库:https://github.com/EaseCloud/docker-django

FROM python:latest 
MAINTAINER huangwc@easecloud.cn 
 
WORKDIR /var/app 
 
ENV PROJECT=app 
 
RUN apt-get update && apt-get upgrade -y && apt-get autoremove -y 
 
RUN pip install --upgrade pip && \ 
    pip install gunicorn django greenlet eventlet 
 
COPY ./startup.sh /var 
RUN chmod +x /var/startup.sh 
 
VOLUME ["/var/app", "/var/app/media"] 
 
EXPOSE 8000 
 
CMD ["/var/startup.sh"] 

因此,我现在使用 CMD 命令运行脚本 startup.sh。

脚本内容为:

#!/bin/bash 
set -e 
if [ ! -e ./manage.py ]; then 
    django-admin startproject $PROJECT . 
fi 
if [ -f ./requirements.txt ]; then 
    pip install -r requirements.txt 
fi 
gunicorn -b 0.0.0.0:8000 -w 4 -k eventlet $PROJECT.wsgi 

在脚本中,我将执行以下操作:

  1. 如果没有源码卷,尝试启动一个django项目;
  2. 在 requirements.txt 中安装 PyPI 要求;
  3. 启动 gunicorn 服务;

问题:

现在,因为平时我会将源代码卷进去,包括requirements.txt,所以我可能对不同的docker容器实例有不同的PyPI要求。

我想做的是:

pip install -r requirements.txt 

仅在我调用 docker run 时执行:

docker run --name myproject \ 
    -v /var/django/myproject:/var/app \ 
    -e PROJECT=myproject \ 
    huangwc/django 

但我不想在调用时运行命令:

docker start myproject 

有什么好的解决方案吗?

请您参考如下方法:

我将稍微扩展 Matt 的评论,并添加另一个想法来实现我根据您的脚本理解的最终目标。

想法 #1:设置开发环境变量

如果将启动脚本修改为如下内容,则可以控制某些组件是否运行:

#!/bin/bash 
set -e 
if [ $DEVELOPMENT ]; then 
  if [ -f ./requirements.txt ]; then 
      pip install -r requirements.txt 
  fi 
  if [ ! -e ./manage.py ]; then 
      exec django-admin startproject $PROJECT . 
  fi 
else 
  exec gunicorn -b 0.0.0.0:8000 -w 4 -k eventlet $PROJECT.wsgi 
fi 

然后在开发环境中运行容器时,将DEVELOPMENT 环境变量设置为true 或其他一些文本。如果没有它(默认情况下),容器将启动 gunicorn 并假定所有依赖项都存在,并且没有代码安装在镜像中构建的内容之上。

想法 #2:分离操作

我非常喜欢默认运行时“正常工作”的图像。因此,如果您可以规定您的默认设置是使用所有代码和依赖项构建镜像(来自构建过程)。然后你生成的 CMD of gunicorn -b 0.0.0.0:8000 -w 4 -k eventlet $PROJECT.wsgi 应该足以做到这一点。

然后在开发方面,只需使用 pip install -r requirements.txt && django-admin 之类的指令在 docker run 手动覆盖 CMD启动项目 $PROJECT .。如果有帮助,您可以将其设为单独的脚本 dev.sh:

#!/bin/bash 
set -e 
pip install -r requirements.txt 
exec django-admin startproject $PROJECT .