在 docker 运行 但在 docker 启动时不执行 CMD

Make a CMD effect on docker run but not in docker start

背景:

我正在使用 docker.

部署 python-web(django) 环境

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

我的 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:分离操作

默认情况下 运行 时,我非常喜欢图像 "that just work"。因此,如果您可以规定您的默认设置是使用所有代码和依赖项构建映像(来自构建过程)。那么你得到的 CMD of gunicorn -b 0.0.0.0:8000 -w 4 -k eventlet $PROJECT.wsgi 应该足以做到这一点。

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

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