使用 Docker 让部署 Django 项目更加轻松

2019-10-1414139 阅读37 评论

之前一系列繁琐的部署步骤让我们感到痛苦。这些痛苦包括:

  • 要去服务器上执行 n 条命令
  • 本地环境和服务器环境不一致,明明本地运行没问题,一部署服务器上就挂挂,死活启动不起来
  • 如果上面的情况发生了,又要去服务器上执行 n 条命令以解决问题
  • 本地更新了代码,部署上线后,上述历史又重演一遍,想死的心都有了

那么我们有没有办法,让本地开发环境和线上环境保持一致?这样我们在部署上线前,就可以在本地进行验证,只要验证没问题,我们就有 99% 的把握保证部署上线后也没有问题(1%保留给程序玄学)。

这个办法就是使用 Docker。

Docker 是一种容器技术,可以为我们提供一个隔离的运行环境。要使用 Docker,首先我们需要编排一个镜像,镜像就是用来描述这个隔离环境应该是什么样子的,它需要安装哪些依赖,需要运行什么应用等,可以把它类比成一搜货轮的制造图。

有了镜像,就可以在系统中构建出一个实际隔离的环境,这个环境被称为容器,就好比根据设计图,工厂制造了一条船。工厂也可以制造无数条这样的船。

容器造好了,只要启动它,隔离环境便运行了起来。由于事先编排好了镜像,因此无论是在本地还是线上,运行的容器内部环境都一样,所以保证了本地和线上环境的一致性,大大减少了因为环境差异导致的各种问题。

所以,我们首先来编排 Docker 镜像。

类似于分离 settings.py 文件为 local.py 和 production.py,我们首先建立如下的目录结构,分别用于存放开发环境的镜像和线上环境的镜像:

HelloDjango-blog-tutorial\
      blog\
      ...
      compose\
            local\
            production\
                  django\
                  nginx\
    ...

local 目录下存放开发环境的 Docker 镜像文件,production 下的 django 文件夹存放基于本项目编排的镜像,由于线上环境还要用到 Nginx,nginx 目录下存放 Nginx 的镜像。

线上环境

镜像文件

我们先来在 production\django 目录下编排博客项目线上环境的镜像文件,镜像文件以 Dockerfile 命名:

FROM python:3.6-alpine

ENV PYTHONUNBUFFERED 1

RUN apk update \
  # Pillow dependencies
  && apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev

WORKDIR /app

RUN pip install pipenv -i https://pypi.douban.com/simple

COPY Pipfile /app/Pipfile
COPY Pipfile.lock /app/Pipfile.lock
RUN pipenv install --system --deploy --ignore-pipfile

COPY . /app

COPY ./compose/production/django/start.sh /start.sh
RUN sed -i 's/\r//' /start.sh
RUN chmod +x /start.sh

首先我们在镜像文件开头使用 FROM python:3.6-alpine 声明此镜像基于 python:3.6-alpine 基础镜像构建。alpine 是一个 Linux 系统发行版,主打小巧、轻量、安全。我们程序运行需要 Python 环境,因此使用这个小巧但包含完整 Python 环境的基础镜像来构建我们的应用镜像。

ENV PYTHONUNBUFFERED 1 设置环境变量 PYTHONUNBUFFERED=1

接下来的一条 RUN 命令安装图像处理包 Pilliow 的依赖,因为如果使用 django 处理图片时,会使用到 Pillow 这个Python 库。

接着使用 WORKDIR /app 设置工作目录,以后在基于此镜像启动的 Docker 容器中执行的命令,都会以这个目录为当前工作目录。

然后我们使用命令 RUN pip install pipenv 安装 pipenv,-i 参数指定 pypi 源,国内一般指定为豆瓣源,这样下载 pipenv 安装包时更快,国外网络可以省略 -i 参数,使用官方的 pypi 源即可。

然后我们将项目依赖文件 Pipfile 和 Pipfile.lock copy 到容器里,运行 pipenv install 安装依赖。指定 --system 参数后 pipenv 不会创建虚拟环境,而是将依赖安装到容器的 Python 环境里。因为容器本身就是个虚拟环境了,所以没必要再创建虚拟环境。

接着将这个项目的文件 copy 到容器的 /app 目录下(当然有些文件对于程序运行是不必要的,所以一会儿我们会设置一个 dockerignore 文件,里面指定的文件不会被 copy 到容器里)。

然后我们还将 start.sh 文件复制到容器的 / 目录下,去掉回车符(windows 专用,容器中是 linux 系统),并赋予了可执行权限。

start.sh 中就是启动 Gunicorn 服务的命令:

#!/bin/sh

python manage.py migrate
python manage.py collectstatic --noinput
gunicorn blogproject.wsgi:application -w 4 -k gthread -b 0.0.0.0:8000 --chdir=/app

我们会让容器启动时去执行此命令,这样就启动了我们的 django 应用。--chdir=/app 表明以 /app 为根目录,这样才能找到 blogproject.wsgi:application。

在项目根目录下建立 .dockerignore 文件,指定 copy 到容器的文件:

.*
_credentials.py
fabfile.py
*.sqlite3

线上环境使用 Nginx,同样来编排 Nginx 的镜像,这个镜像文件放到 compose\production\nginx 目录下:

FROM nginx:1.17.1

# 替换为国内源
RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak
COPY ./compose/production/nginx/sources.list /etc/apt/
RUN apt-get update && apt-get install -y --allow-unauthenticated certbot python-certbot-nginx

RUN rm /etc/nginx/conf.d/default.conf
COPY ./compose/production/nginx/HelloDjango-blog-tutorial.conf /etc/nginx/conf.d/HelloDjango-blog-tutorial.conf

这个镜像基于 nginx:1.17.1 基础镜像构建,然后我们更新系统并安装 certbot 用于配置 https 证书。由于要安装大量依赖, nginx:1.17.1 镜像基于 ubuntu,所以安装会比较慢,我们将软件源替换为国内源,这样稍微提高一下安装速度。

最后就是把应用的 nginx 配置复制到容器中 nginx 的 conf.d 目录下。里面的内容和直接在系统中配置 nginx 是一样的。

upstream hellodjango_blog_tutorial  {
    server hellodjango_blog_tutorial:8000;
}

server {
    server_name  hellodjango-blog-tutorial-demo.zmrenwu.com;

    location /static {
        alias /apps/hellodjango_blog_tutorial/static;
    }

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass http://hellodjango_blog_tutorial;
    }

    listen 80;
}

相比之前直接在宿主机配置 Nginx,这里使用了 Nginx 的 upstream 模块,实际上就是做一个请求转发。Nginx 将所有请求转发给上游 hellodjango_blog_tutorial 模块处理,而 hellodjango_blog_tutorial 这个模块的服务实际就是运行 django 应用的容器 hellodjango_blog_tutorial(接下来会运行这个容器)。

镜像编排完毕,接下来就可以通过镜像构建容器并运行容器了。但是先等一等,我们有两个镜像,一个是 django 应用的,一个是 Nginx 的,这意味着我们需要构建 2 次容器,并且启动容器 2 次,这会比较麻烦。有没有办法一次构建,一条命令运行呢?答案就是使用 docker-compose。

docker-compose 将各个容器的镜像,以及构建和运行容器镜像时的参数等编写在一个 ymal 文件里。这样我们只需要一条 build 命令就可以构建多个容器,使用一条命令 up 就可以启动多个容器。

我们在项目根目录建一个 production.yml 文件来编排 django 容器和 nginx 容器。

version: '3'

volumes:
  static:
  database:

services:
  hellodjango_blog_tutorial:
    build:
      context: .
      dockerfile: compose/production/django/Dockerfile
    image: hellodjango_blog_tutorial
    container_name: hellodjango_blog_tutorial
    working_dir: /app
    volumes:
      - database:/app/database
      - static:/app/static
    env_file:
      - .envs/.production
    ports:
      - "8000:8000"
    command: /start.sh

  nginx:
    build:
      context: .
      dockerfile: compose/production/nginx/Dockerfile
    image: hellodjango_blog_tutorial_nginx
    container_name: hellodjango_blog_tutorial_nginx
    volumes:
      - static:/apps/hellodjango_blog_tutorial/static
    ports:
      - "80:80"
      - "443:443"

version: '3' 声明 docker-compose 为第三代版本的语法

volumes:
  static:
  database:

声明了 2 个命名数据卷,分别为 static 和 database。数据卷是用来干嘛的呢?由于 docker 容器是一个隔离环境,一旦容器被删除,容器内的文件就会一并删除。试想,如果我们启动了博客应用的容器并运行,一段时间后,容器中的数据库就会产生数据。后来我们更新了代码或者修改了容器的镜像,这个时候就要删除旧容器,然后重新构建新的容器并运行,那么旧容器中的数据库就会连同容器一并删除,我们辛苦写的博客文章付之一炬。

所以我们使用 docker 的数据卷来管理需要持久存储的数据,只要数据被 docker 的数据卷管理起来了,那么新的容器启动时,就可以从数据卷取数据,从而恢复被删除容器里的数据。

我们有 2 个数据需要被数据卷管理,一个是数据库文件,一个是应用的静态文件。数据库文件容易理解,那么为什么静态文件也要数据卷管理呢?启动新的容器后使用 python manage.py collectstatic 命令重新收集不就好了?

答案是不行,数据卷不仅有持久保存数据的功能,还有跨容器共享文件的功能。要知道,容器不仅和宿主机隔离,而且容器之间也是互相隔离的。Nginx 运行于独立容器,那么它处理的静态文件从哪里来呢?应用的静态文件存放于应用容器,Nginx 容器是访问不到的,所以这些文件也通过数据卷管理,nginx 容器从数据卷中取静态文件映射到自己的容器内部。

接下来定义了 2 个 services,一个是应用服务 hellodjango_blog_tutorial,一个是 nginx 服务。

build:
  context: .
  dockerfile: compose/production/django/Dockerfile

告诉 docker-compose,构建容器是基于当前目录(yml 文件所在的目录),且使用的镜像是 dockerfile 指定路径下的镜像文件。

image 和 container_name 分别给构建的镜像和容器取个名字。

working_dir 指定工作目录。

volumes:
  - database:/app/database
  - static:/app/static

建立数据卷和容器中文件的映射关系。

同时这里要注意,数据卷只能映射文件夹而不能映射单一的文件,所以对我们应用的数据库来说,db.sqlite3 文件我们把它挪到了 database 目录下。因此我们要改一下 django 的配置文件中数据库的配置,让它正确地将数据库文件生成在项目根目录下的 database 文件夹下:

DATABASES = {
    'default': {
         'ENGINE': 'django.db.backends.sqlite3',
         'NAME': os.path.join(BASE_DIR, 'database', 'db.sqlite3'),
    }
}
env_file:
  - .envs/.production

容器启动时读取 .envs/.production文件中的内容,将其注入环境变量。

我们创建一下这个文件,把 secret_key 写进去。

DJANGO_SECRET_KEY=2pe8eih8oah2_2z1=7f84bzme7^bwuto7y&f(#@rgd9ux9mp-3

注意将这些包含敏感信息的文件加入版本控制工具的忽略列表里,防止一不小心推送到公开仓库供大众观光。

ports:
  - "8000:8000"

暴露容器内的 8000 端口并且和宿主机的 8000 端口绑定,于是我们就可以通过宿主机的 8000 端口访问容器。

command: /start.sh 容器启动时将执行 start.sh,从而启动 django应用。

nginx 服务容器也类似,只是注意它从数据卷 static 中取静态文件并映射到 nginx 容器内的 /apps/hellodjango_blog_tutorial/static,所以我们在 nginx 的配置中:

location /static {
    alias /apps/hellodjango_blog_tutorial/static;
}

这样可以正确代理静态文件。

万事具备,在本地执行一下下面的两条命令来构建容器和启动容器。

docker-compose -f production.yml build
docker-compose -f production.yml up

此时我们可以通过域名来访问容器内的应用,当然,由于 Nginx 在本地环境的容器内运行,需要修改一下 本地 hosts 文件,让域名解析为本地 ip 即可。

如果本地访问没有问题了,那么就可以直接在服务器上执行上面两条命令以同样的方式启动容器,django 应用就顺利地在服务上部署了。

开发环境

既然线上环境都使用 Docker 了,不妨开发环境也一并使用 Docker 进行开发。开发环境的镜像和 docker-compose 文件比线上环境简单一点,因为不用使用 nginx。

开发环境的镜像文件,放到 compose\local 下:

FROM python:3.6-alpine

ENV PYTHONUNBUFFERED 1

RUN apk update \
  # Pillow dependencies
  && apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev

WORKDIR /app

RUN pip install pipenv -i https://pypi.douban.com/simple

COPY Pipfile /app/Pipfile
COPY Pipfile.lock /app/Pipfile.lock
RUN pipenv install --system --deploy --ignore-pipfile

COPY ./compose/local/start.sh /start.sh
RUN sed -i 's/\r//' /start.sh
RUN chmod +x /start.sh

要注意和线上环境不同的是,我们没有把整个代码 copy 到容器里。线上环境代码一般比较稳定,而对于开发环境,由于需要频繁修改和调试代码,如果我们把代码 copy 到容器,那么容器外做的代码修改,容器内部是无法感知的,这样容器内运行的应用就没法同步我们的修改了。所以我们会把代码通过 Docker 的数据卷来管理。

start.sh 不再启动 gunicorn,而是使用 runserver 启动开发服务器。

#!/bin/sh

python manage.py migrate
python manage.py runserver 0.0.0.0:8000

然后创建一个 docker-compose 文件 local.yml(和 production.yml 同级),用于管理开发容器。

version: '3'

volumes:
  database_local:

services:
  hellodjango_blog_tutorial_local:
    build:
      context: .
      dockerfile: ./compose/local/Dockerfile
    image: hellodjango_blog_tutorial_local
    container_name: hellodjango_blog_tutorial_local
    working_dir: /app
    volumes:
      - database_local:/app/database
      - .:/app
    ports:
      - "8000:8000"
    command: /start.sh

注意我们将整个项目根目录下的文件挂载到了 /app 目录下,这样就能容器内就能实时反映代码的修改了。

线上部署

如果容器在本地运行没有问题了,线上环境的容器运行也没有问题,因为理论上,我们在线上服务器也会构建和本地测试用的容器一模一样的环境,所以几乎可以肯定,只要我们服务器有 Docker,那么我们的应用就可以成功运行。

首先在服务安装 Docker,安装方式因系统而异,方式非常简单,我们以 CentOS 7 为例,其它系统请参考 Docker 的官方文档

首先安装必要依赖:

$ sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

然后添加仓库源:

$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

最后安装 Docker:

$ sudo yum install docker-ce docker-ce-cli containerd.io

启动 Docker:

$ sudo systemctl start docker

(境外服务器忽略)设置 Docker 源加速(使用 daocloud 提供的镜像源),否则拉取镜像时会非常慢

curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io

在 docker 中运行一个 hello world,确认 docker 安装成功:

$ sudo docker run hello-world

docker 安装成功了,还要安装一下 docker-compose。其实是一个 python 包,我们直接通过 pip 安装就可以了:

$ pip install docker-compose

为了避免运行一些 docker 命令时可能产生的权限问题,我们把系统当前用户加入到 docker 组里:

$ sudo usermod -aG docker ${USER}

添加组后要重启一下 shell(ssh 连接的话就断开重连)。

万事俱备,只欠东风了!

开始准备让我们的应用在 docker 容器里运行。由于之前我们把应用部署在宿主机上,首先来把相关的服务停掉:

# 停掉 nginx,因为我们将在容器中运行 nginx
$ sudo systemctl stop nginx

# 停掉博客应用
$ supervisorctl stop hellodjango-blog-tutorial -c ~/etc/supervisord.conf

接下来拉取最新的代码到服务器,进入项目根目录下,创建线上环境需要的环境变量文件:

$ mkdir .envs
$ cd .envs
$ vi .production

将线上环境的 secret key 写入 .production 环境变量文件,

DJANGO_SECRET_KEY=2pe8eih8oah2_2z1=7f84bzme7^bwuto7y&f(#@rgd9ux9mp-3

保存并退出。

回到项目根目录,运行 build 命令构建镜像:

$ docker-compose -f prodcution.yml build

然后我们可以开始启动根据构建好的镜像启动 docker 容器,不过为了方便,我们的 docker 进程仍然由 supervisor 来管理,我们修改一下博客应用的配置,让它启动时启动 docker 容器。

打开 ~/etc/supervisor/conf.d/hellodjango-blog-tutorial.ini,修改为如下内容:

[program:hellodjango-blog-tutorial]
command=docker-compose -f production.yml up --build
directory=/home/yangxg/apps/HelloDjango-blog-tutorial
autostart=true
autorestart=unexpected
user=yangxg
stdout_logfile=/home/yangxg/etc/supervisor/var/log/hellodjango-blog-tutorial-stdout.log
stderr_logfile=/home/yangxg/etc/supervisor/var/log/hellodjango-blog-tutorial-stderr.log

主要就是把之前的使用 Gunicorn 来启动服务换成了启动 docker。

修改 ini 配置 要记得 reread 使配置生效:

$ supervisorctl -c ~/etc/supervisord.conf
> reread
> start 

docker 容器顺利启动,访问我们的博客网站。抛掉镜像编排的准备工作,相当于我们只执行了一条构建容器并启动容器的命令就部署了我们的博客应用。如果换台服务器,也只要再执行一下镜像构建和启动容器的命令,服务就又可以起来!这就是 docker 的好处。

由于开发 django 用的最多的 IDE Pycharm 也能很好地集成 Docker,我现在开发工作已经全面拥抱 Docker 了,前所未有的体验,前所未有的方便和稳定,一定要学着用起来!

HTTPS

最后,由于 Nginx 在新的容器里运行,所以需要重新申请和配置 https 证书,这和之前是一样,只是此前 Nginx 在宿主机上,这次我们在容器里运行 certbot 命令。编排 nginx 镜像时已经安装了 certbot,直接执行命令即可,在 docker 容器内执行命令如下:

我们首先通过 docker ps 命令查看正在运行的容器,记住 nginx 容器的名字,然后使用 docker exec -it 容器名 命令的格式在指定容器内执行命令,所以我们执行:

$ docker exec -it nginx certbot --nginx

根据提示输入信息即可,过程和上一节在宿主机上部署一模一样,这里不再重复。

自动化部署

fabric 无需修改,来尝试本地执行一下:

pipenv run fab -H server_ip --prompt-for-login-password -p deploy

完美!至此,我们的博客已经稳定运行于线上,陆陆续续会有更多的人来访问我们的博客,让我们来继续完善它的功能吧!

-- EOF --

37 评论
登录后回复
一叶寒
2021-07-30 22:50:33

我部署后,后台显示丢失了模板,很乱的那种,是可能出现的状况吗

回复
一叶寒
2021-07-30 02:47:12

ImproperlyConfigured: The SECRET_KEY setting must not be empty.
不知道为什么出现了这个错误,我也创建了那个环境文件,将这个值写在了里面

回复
Hughes Nick
2021-03-25 02:37:28

ERROR: unsatisfiable constraints:
  jpep-dev (missing):
    required by: world[jpep-dev]
  openjpep-dev (missing):
    required by: world[openjpep-dev]
ERROR: Service 'hellodjango_blog_tutorial' failed to build: The command '/bin/sh -c apk update   && apk add jpep-dev zlib-dev freetype-dev lcms2-dev openjpep-dev tiff-dev tk-dev tcl-dev' returned a non-zero code: 2

第一个没发好,看这个吧,jpep-dev和openjpep-dev,一直卡在这了

回复
Hughes Nick
2021-03-25 02:36:21

```ERROR: unsatisfiable constraints:
jpep-dev (missing):
required by: world[jpep-dev]
openjpep-dev (missing):
required by: world[openjpep-dev]
ERROR: Service 'hellodjango_blog_tutorial' failed to build: The command '/bin/sh -c apk update && apk add jpep-dev zlib-dev freetype-dev lcms2-dev openjpep-dev tiff-dev tk-dev tcl-dev' returned a non-zero code: 2

```

这两个包安装不下来咋办,求助一下

回复
机制的老鸟
2020-08-18 14:35:52

谢谢博主的文章,通过学习我有两个疑问:
1.如下图,两个容器的static 数据卷为什么不是同一个目录?我的理解是nginx中的这个数据卷是持久化作用,但是不太理解django容器中的static数据卷有什么作用,共享吗?静态资源不用django处理了,还要共享干嘛?
image.png

2.把所有的文件拷贝至/app中,那么当我的源代码做了修改,我是否需要重新build这个镜像?这样不是太浪费时间了嘛,又要重新下载一大堆依赖。能不能实现随意修改代码,容器直接重启就可以更新?
image.png

回复
追梦人物 机制的老鸟
2020-10-19 11:59:20
  1. 静态资源是在 django 容器里的,Nginx 要访问的话,我这里用的方式就是数据卷共享。相当于 django 容器把静态资源丢到了数据卷里,Nginx 去数据卷读。
  2. 修改代码就要重新build这个镜像,Docker 有镜像层缓存,build 也不是很慢。
回复
Jack
2020-08-04 22:50:03

好奇用了docker还有必要加上supervisor吗?docker-compose up 有个 -d 可以守护进程运行,请问这个跟supervisor有什么区别吗?

回复
追梦人物 Jack
2020-10-19 12:00:39

其实是的,只是上一步教程已经配了 supervisor,所以复用了,直接部署的话 docker 就够了。

回复
LeechenLove
2020-07-12 16:14:15

谢谢博主,教程非常详细
Docker部署没有成功,暂时没有解决,遇到挺多问题
要是有视频就更好了(来自小白的恳求呜呜~),加油吧,看完后面的再回来解决如何Docker部署吧

回复
linlanniao
2020-07-08 12:07:12

贡献一个Dockerfile,multi的打包方式打出来的镜像会更小一些

### base
FROM python:3.8-alpine as base
ENV PYTHONUNBUFFERED 1
ENV PIPENV_VENV_IN_PROJECT 1
ENV PATH "/app/.venv/bin:$PATH"
WORKDIR /app

### build
FROM base AS builder
COPY Pipfile Pipfile.lock ./
COPY ./compose/production/django/start.sh ./start.sh
COPY . /app
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories  && \
    apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev musl-dev libffi-dev openssl-dev python3-dev gcc
RUN pip install pipenv -i https://mirrors.aliyun.com/pypi/simple  && \
# RUN pipenv install --system --deploy --ignore-pipfile
    pipenv install --deploy --ignore-pipfile
RUN sed -i 's/\r//' ./start.sh && chmod +x ./start.sh

### runner
FROM base
COPY --from=builder /app /app
EXPOSE 8000
CMD [ "./start.sh" ]

回复
追梦人物 linlanniao
2020-07-19 20:31:24

非常感谢,目前我也在研究新的打包方式了。

回复
yhitee
2020-06-11 21:43:06

请教下 production.yml 下的nginx

这样写会不会更好一点,指定上下文路径,build的时候不用发送整个目录,加快构建~

nginx:
    build:
      context: compose/production/nginx/
      dockerfile: Dockerfile

回复
二十八画生1988
2020-06-02 16:18:23

博主,在生成镜像时报错了,请忙看一下,谢谢!
Installing dependencies from Pipfile.lock (67746f)…
Failed to load paths: /bin/sh: /root/.local/share/virtualenvs/app-4PlAip0Q/bin/python: not found

Output:
Failed to load paths: /bin/sh: /root/.local/share/virtualenvs/app-4PlAip0Q/bin/python: not found

Output:
Failed to load paths: /bin/sh: /root/.local/share/virtualenvs/app-4PlAip0Q/bin/python: not found

Output:
An error occurred while installing regex==2020.5.14 --hash=sha256:c2062c7d470751b648f1cacc3f54460aebfc261285f14bc6da49c6943bd48bdd --hash=sha256:ce450ffbfec93821ab1fea94779a8440e10cf63819be6e176eb1973a6017aff5 --hash=sha256:329ba35d711e3428db6b45a53b1b13a0a8ba07cbbcf10bbed291a7da45f106c3 --hash=sha256:ea55b80eb0d1c3f1d8d784264a6764f931e172480a2f1868f2536444c5f01e01 --hash=sha256:a7c37f048ec3920783abab99f8f4036561a174f1314302ccfa4e9ad31cb00eb4 --hash=sha256:579ea215c81d18da550b62ff97ee187b99f1b135fd894a13451e00986a080cad --hash=sha256:1386e75c9d1574f6aa2e4eb5355374c8e55f9aac97e224a8a5a6abded0f9c927 --hash=sha256:51f17abbe973c7673a61863516bdc9c0ef467407a940f39501e786a07406699c --hash=sha256:70c14743320a68c5dac7fc5a0f685be63bc2024b062fe2aaccc4acc3d01b14a1 --hash=sha256:c9bce6e006fbe771a02bda468ec40ffccbf954803b470a0345ad39c603402577 --hash=sha256:27ff7325b297fb6e5ebb70d10437592433601c423f5acf86e5bc1ee2919b9561 --hash=sha256:ce5cc53aa9fbbf6712e92c7cf268274eaff30f6bd12a0754e8133d85a8fb0f5f --hash=sha256:d466967ac8e45244b9dfe302bbe5e3337f8dc4dec8d7d10f5e950d83b140d33a --hash=sha256:e565569fc28e3ba3e475ec344d87ed3cd8ba2d575335359749298a0899fe122e --hash=sha256:89d76ce33d3266173f5be80bd4efcbd5196cafc34100fdab814f9b228dee0fa4 --hash=sha256:99568f00f7bf820c620f01721485cad230f3fb28f57d8fbf4a7967ec2e446994 --hash=sha256:7e61be8a2900897803c293247ef87366d5df86bf701083b6c43119c7c6c99108 --hash=sha256:ce367d21f33e23a84fb83a641b3834dd7dd8e9318ad8ff677fbfae5915a239f7 --hash=sha256:3a9394197664e35566242686d84dfd264c07b20f93514e2e09d3c2b3ffdf78fe --hash=sha256:d881c2e657c51d89f02ae4c21d9adbef76b8325fe4d5cf0e9ad62f850f3a98fd --hash=sha256:8044d1c085d49673aadb3d7dc20ef5cb5b030c7a4fa253a593dda2eab3059929! Will try again.
The command '/bin/sh -c pipenv install --system --deploy --ignore-pipfile' returned a non-zero code: 1

回复
lykloveyou
2020-05-01 08:32:22

在执行docker-compose -f local.yml up --build的时候出现如下错误,麻烦老师帮忙看下
An error occurred while installing bcrypt==3.1.7 --hash

An error occurred while installing cffi==1.14.0 --hash

An error occurred while installing cryptography==2.8 --hash=

An error occurred while installing pynacl==1.3.0 --hash=
image.png

image.png

image.png

回复
追梦人物 lykloveyou
2020-05-05 11:04:22

图片无法显示,直接贴文字比较好。

可能原因就是网络不行,多试几次,或者在 Pipfile 中将 pip 源改为国内的源(在大陆的话)。

回复
literence
2020-04-23 09:18:37

ERROR: Couldn't connect to Docker daemon at http+docker://localunixsocket - is it running?

If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.

请问这是什么问题

回复
追梦人物 literence
2020-05-05 11:17:26

没有启动 docker

回复
aha
2020-03-16 13:50:39

求助博主,docker构建python:3.6-alpine无法下载任何软件,也不能apk update,报同一个错误。更换软件源重启docker也没用。

ERROR: http://dl-cdn.alpinelinux.org/alpine/v3.11/main: temporary error (try again later)
WARNING: Ignoring APKINDEX.70f61090.tar.gz: No such file or directory
ERROR: http://dl-cdn.alpinelinux.org/alpine/v3.11/community: temporary error (try again later)
WARNING: Ignoring APKINDEX.ca2fea5b.tar.gz: No such file or directory

回复
aha aha
2020-03-16 21:41:58

还有使用其他linux都是定位不到包,不能update不能下载软件T_T失了改dns换源都没用

回复
追梦人物 aha
2020-03-21 16:50:16

这个问题还真没遇到过,google 搜索一下报错信息看有没有相关的解决方案。

回复
yangke861
2020-03-13 15:59:09

0.0.0.0:8000->8000/tcp untitled3
0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp untitled3_nginx
访问IP:8000 显示Server Error (500)
我修改了Nginx代理,还是这样。博主怎么看?

回复
追梦人物 yangke861
2020-03-21 16:48:56

500 是后端错误,看下具体的代码报错日志定位问题

回复
yangke861
2020-03-06 15:33:46

6#6: *2 connect() failed (113: No route to host) while connecting to upstream, client: 106.36.217.42, server: 39.98.149.224, request: "GET / HTTP/1.1", upstream: "http://172.18.0.2:8000/", host: "39.98.149.224"

回复
yangke861
2020-03-05 16:04:05

麻烦博主给点支持。。
docker中项目容器启动不起来,报错说“找不到什么主机”。怎么破?

回复
追梦人物 yangke861
2020-03-05 18:41:51

报错信息贴出来看下咯,没有任何错误消息咋定位问题?

回复
yangke861 追梦人物
2020-03-06 10:53:31

流程走完了,就是输入ip后,显示无法访问。
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
46c0cb8a316e untitled3 "/start.sh" 18 hours ago Up 4 seconds 0.0.0.0:8000->8000/tcp untitled3
760d54a196f3 e4a2c06bcae0 "nginx -g 'daemon of…" 43 hours ago Exited (1) About an hour ago pensive_lamport
9829ce32ae26 332b783deb4b "/bin/sh -c 'apt-get…" 44 hours ago Exited (100) 44 hours ago eloquent_goldstine
77762c1f2450 332b783deb4b "/bin/sh -c 'apt-get…" 47 hours ago Exited (100) 47 hours ago kind_bose
437889dbc829 89e7b401898e "/bin/sh -c 'apk upd…" 2 days ago Exited (1) 47 hours ago cool_shannon
800037a59720 hello-world "/hello" 2 days ago Exited (0) 2 days ago adoring_engelbart

回复
yangke861 追梦人物
2020-03-06 11:13:42

感觉是nginx容器没启动起来。
ERROR: for nginx Cannot create container for service nginx: invalid volume specification: 'untitled3_static:apps/FirstDjango/untitled3/static:rw': invalid mount config for type "volume": invalid mount path: 'apps/FirstDjango/untitled3/static' mount path must be absolute
ERROR: Encountered errors while bringing up the project.

回复
yangke861 追梦人物
2020-03-06 14:42:06

项目容器报错信息:
File "/app/untitled3/wsgi.py", line 12, in
from django.core.wsgi import get_wsgi_application
ModuleNotFoundError: No module named 'django'
docker 中需要安装 Django 吗?

回复
追梦人物 yangke861
2020-03-07 00:16:36
  1. 数据卷命名好像有问题
  2. 没有安装 django,所以报错了
回复
fadeawaylove
2020-02-09 14:23:17

出现错误:

Couldn't connect to Docker daemon at http+docker://localhost - is it running?

If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
Couldn't connect to Docker daemon at http+docker://localhost - is it running?

If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
Couldn't connect to Docker daemon at http+docker://localhost - is it running?

If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
Couldn't connect to Docker daemon at http+docker://localhost - is it running?

If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.

配置文件中:
command=docker-compose -f production.yml up --build
directory=/home/daigua/code/dogBlog

实际在项目目录下运行docker-compose -f production.yml up也没问题

回复
赖凌锋
2019-11-01 11:00:17

为什么 production\django\Dockerfile 中的
COPY . /app
是“接着将这个项目的文件 copy 到容器的 /app 目录下”,Dockerfile 所在的目录不是compose\production\django 吗,因为用compose启动的dockerfile,它的文件production.yml所在目录是根目录?

回复
追梦人物 赖凌锋
2019-11-03 13:17:55

是的,这个相对路径相对于 production.yml 所在目录。

回复
boyang
2019-10-15 16:47:27

能讲一下windows server下如何部署吗?

回复
追梦人物 boyang
2019-10-16 10:29:15

windows更加简单呀,和你本地开发是一样的,如果你本地也是用的windows

回复
Andy-tanbin
2019-10-15 11:55:43

感谢博主,一步步跟住博主做了一些,有些收获,希望接下来的Vue,前后端分离等,快点更新,哈哈,顺便问下博主能新增django + celery 教程吗? celery异步处理,听说很不错哇,有这方面的计划吗?

回复
追梦人物 Andy-tanbin
2019-10-15 12:09:56

可以先参考网上一些其他文章,后续会出。

回复
Andy-tanbin 追梦人物
2019-10-15 14:01:48

好的,会持续关注的~

回复