Docker学习,我是这样解决的

介绍

《两年个人发展》结尾学习Docker的样板网站这是我工作时的记录。希望不强不强的人可以参考一下自己在阅读本站时卡住的地方。

目标听众

针对 Django 用户和 Docker 初学者。我希望它能帮助那些希望能够使用 Docker 进行个人开发的人。

开发环境

视窗 11 专业版 (二!)

我没有在 Home 上尝试过,但应该没问题。 建议您拥有多台 PC,尤其是当您是初学者且解决问题的能力较低时。注重性价比,二手还行。拥有一台可以随时安装干净操作系统的机器令人放心。 我写这篇文章,好像我一口气完成了工作,但实际上我对很多事情上瘾了。在我通过谷歌搜索英文网站尝试了各种方法但没有找到解决方案的情况下,我在另一台 PC 上以相同的方式设置环境并执行相同的工作,并且能够使其正常工作。什么已经Docker学習、私はこう取り組んだ

WSL2 Ubuntu

似乎有多种安装程序,但我认为其中任何一种都可以。

代码

确保您可以在 VScode 终端中操作 WSL2 Ubuntu bash。请谷歌环境设置并寻找一个易于理解的网站。

Python

不要使用 WSL2 Ubuntu 附带的 Python,安装更新版本的 Python 并使用它。 我安装了与模型相同的Ver.3.9.6。 从头开始重温构建工作

从创建项目目录开始,带你到最后,中间不跳。惊人。当我学习时,我写下了我与模型不同的地方,我有什么问题,我解决了什么,以及模型站点的进展情况。标题是相关项目的链接。由于仔细解释的部分不在本文中转载,首先,请看一下链接的网站Docker学習、私はこう取り組んだ也就是说,有很多地方我写了一个很好的例子,只是为了帮助你了解这个过程而不必来回走动。 (因为我想在空白之后把它变成我自己的工作程序手册..)

阅读英文网站时,我们推荐使用 DeepL 应用程序版本。选择一个字符后,按 Ctrl 键并按两次 C 键将立即翻译它。这是一个了不起的时刻。即使使用谷歌翻译,示例网站也可能很容易理解。

在你的主目录中准备一个工作区(命名为works)

~$ mkdir works
~$ cd works

准备一个项目目录(命名为 hoge-on-docker)

~/works$ mkdir hoge-on-docker
~/works$ cd hoge-on-docker
~/works/hoge-on-docker$ 

由于PATH很长,在此之后的解释中

~/*$

并表达。

准备一个应用目录来存储 Django 应用

~/*$ mkdir app
~/*$ cd app

Python 虚拟化

~/*/app$ python3 -m venv .
~/*/app$ . .venv/bin/activate

恢复工作时的虚拟化虚拟化命令是. ./app/.venv/bin/activate,因为它可能会在~/*$ 的状态下恢复工作。当然,根据参考站点,source ./app/.venv/bin/activate 很好。我只想记录一下,有两种写法。

安装 Django

Django 版本是目前最新的。我没有安全专业知识,所以我的想法是至少使用新版本的框架。

(.venv)~/*/app$ pip install --upgrade pip
(.venv)~/*/app$ pip install django==4.1
(.venv)~/*/app$ django-admin startproject config .
(.venv)~/*/app$ python manage.py migrate
(.venv)~/*/app$ python manage.py runserver

在浏览器中访问http://localhost:8000/。好的,如果火箭显示。停在ctrl + c。

关于目录名称到现在按照​​​​的思路,将settings.py等存放的文件夹名称设置为config。在切换到 Docker 开发时,我考虑过使用项目名称(在本例中为 hoge),但我决定使用 config.此外,存储 Django 应用程序的目录名称是 app,就像模型一样。原因如下。

目录名为app、config的原因 说到Docker开发,在项目目录下直接有docker-compose.yml等很多文件。如果您自己制定“Django 应用程序直接位于应用程序文件夹下”的规则,则更容易找到它。 可以统一docker-compose.yml等的描述。 可能很难知道这个django app是谁,有app目录和config,但没关系,看项目目录名就知道了。如果和 config统一,还可以修复后面会出现的nginx.conf的描述。

app 直接在目录下准备requirements.txt,里面填django==4.1。

为什么不使用pip freeze > requirements.txt?基于 python alpine 镜像,我在构建镜像的过程中安装了 Django 环境,所以我不想在 requirements.txt 中包含额外的包信息。我想要的是安装说明列表和安装包列表事实并非如此。

由于数据库使用 Postgres,删除db.sqlite3。由于在构建图像时复制了应用程序的内部,因此想法是提前删除不必要的东西。我有一种感觉,它会在以后的工作中复活,但你可以再次抹去它。(.dockerignore 查找如何处理文件并尝试合并它可能是个好主意。如果你不这样做,我很抱歉Docker学習、私はこう取り組んだ

在app目录下直接创建Dockerfile。 (详情请查看参考网站)

# pull official base image
FROM python:3.9.6-alpine

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt

# copy project
COPY . .

注意文件名中的拼写错误文件名为 d孩子我沉迷于它,因为它是一个 kerfile。如果是VScode,如果文件名正确,图标将是鲸鱼。我得仔细看看。 .

基础镜像版本使用最新版镜像的时候,无法绑定mount(主机和容器互锁),所以就照着做了。我又试了一次,它奏效了,但我认为还有另一个原因。未验证。 .

在项目根目录下创建docker-compose.yml(直接在hoge-on-docker下)(与app相同的层次结构)

码头工人-compose.yml
version: '3.8'

services:
  web:
    build: ./app
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./app/:/usr/src/app/
    ports:
      - 8000:8000
    env_file:
      - ./.env.dev

接下来,在项目根目录中创建.env.dev。

.恩诉在 v
DEBUG=1
SECRET_KEY=〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]

在SECRET_KEY右侧,将settings.pySECRET_KEY的''包围的字符串复制粘贴到app/config目录下。

添加/更改为settings.py

添加/修改settings.py(其他内容省略)
# 冒頭に追記
import os

# 下記3項目の右辺を変更
SECRET_KEY = os.environ.get("SECRET_KEY")
DEBUG = int(os.environ.get("DEBUG", default=0))
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")

图像构建

直接移到项目下

~/*/app$ cd ..

使用 docker-compose.yml 构建镜像

~/*$ docker-compose build

生成一个容器并在后台工作(守护进程)

~/*$ docker-compose up -d

访问。

检查日志如果没有出现火箭屏幕,请检查日志。~/*$ docker-compose 日志 -f

介绍 Postgres。将 db 信息添加到 docker-compose.yml。

码头工人-compose.yml
version: '3.8'

services:
  web:
    build: ./app
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./app/:/usr/src/app/
    ports:
      - 8000:8000
    env_file:
      - ./.env.dev
    depends_on:
      - db
  db:
    image: postgres:13.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - POSTGRES_USER=hello_django
      - POSTGRES_PASSWORD=hello_django
      - POSTGRES_DB=hello_django_dev

volumes:
  postgres_data:

数据库用户名等在示例之后,它仍然是 hello_django,但暂时按原样进行。如果你觉得以后会有问题,那就到时候换。

附加到 .env.dev

.恩诉在 v
DEBUG=1
SECRET_KEY=〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=hello_django_dev
SQL_USER=hello_django
SQL_PASSWORD=hello_django
SQL_HOST=db
SQL_PORT=5432

修改settings.py

settings.py 的一部分
DATABASES = {
    "default": {
        "ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
        "NAME": os.environ.get("SQL_DATABASE", BASE_DIR / "db.sqlite3"),
        "USER": os.environ.get("SQL_USER", "user"),
        "PASSWORD": os.environ.get("SQL_PASSWORD", "password"),
        "HOST": os.environ.get("SQL_HOST", "localhost"),
        "PORT": os.environ.get("SQL_PORT", "5432"),
    }
}

修改 Dockerfile

Dockerfile
# pull official base image
FROM python:3.9.6-alpine

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install psycopg2 dependencies
RUN apk update \
    && apk add postgresql-dev gcc python3-dev musl-dev

# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt

# copy project
COPY . .

作为 psycopg2 安装所需的工作RUN apk update \ && apk add postgresql-dev gcc python3-dev musl-dev之所以实现,是因为它使用了基于 alpine 的图像。当我第一次接受挑战时,我觉得以苗条的形象没有必要。 (我记得...)如果你做额外的事情,你会上瘾,所以如果你不习惯它,请按照示例并使用 alpineDocker学習、私はこう取り組んだ

附加到 requirements.txt

要求.txt
django==4.1
psycopg2-binary==2.9.1

这是如何同时编写镜像构建和启动容器。

~/*$ docker-compose up -d --build

迁移

~/*$ docker-compose exec web python manage.py migrate --noinput

如果您在此处遇到错误,请检查示例站点。

如果 Postgres 正在运行,您应该能够看到创建的默认 Django 表。

~/*$ docker-compose exec db psql --username=hello_django --dbname=hello_django_dev

下面是=#右侧要输入的命令。

psql (13.0)
Type "help" for help.

hello_django_dev=# \l
                                          List of databases
       Name       |    Owner     | Encoding |  Collate   |   Ctype    |       Access privileges
------------------+--------------+----------+------------+------------+-------------------------------
 hello_django_dev | hello_django | UTF8     | en_US.utf8 | en_US.utf8 |
 postgres         | hello_django | UTF8     | en_US.utf8 | en_US.utf8 |
 template0        | hello_django | UTF8     | en_US.utf8 | en_US.utf8 | =c/hello_django              +
                  |              |          |            |            | hello_django=CTc/hello_django
 template1        | hello_django | UTF8     | en_US.utf8 | en_US.utf8 | =c/hello_django              +
                  |              |          |            |            | hello_django=CTc/hello_django
(4 rows)

hello_django_dev=# \c hello_django_dev
You are now connected to database "hello_django_dev" as user "hello_django".

hello_django_dev=# \dt
                     List of relations
 Schema |            Name            | Type  |    Owner
--------+----------------------------+-------+--------------
 public | auth_group                 | table | hello_django
 public | auth_group_permissions     | table | hello_django
 public | auth_permission            | table | hello_django
 public | auth_user                  | table | hello_django
 public | auth_user_groups           | table | hello_django
 public | auth_user_user_permissions | table | hello_django
 public | django_admin_log           | table | hello_django
 public | django_content_type        | table | hello_django
 public | django_migrations          | table | hello_django
 public | django_session             | table | hello_django
(10 rows)

hello_django_dev=# \q

检查卷详细信息

~/*$ docker volume inspect hoge-on-docker_postgres_data
                ↑ _postgres_dataの前はプロジェクト名。自分の環境に合わせる。

如果包含以下显示就可以了

[
    {
        "CreatedAt": "2021-08-23T15:49:08Z",
        "Driver": "local",
        "Labels": {
            "com.docker.compose.project": "hoge-on-docker",
            "com.docker.compose.version": "1.29.2",
            "com.docker.compose.volume": "postgres_data"
        },
        "Mountpoint": "/var/lib/docker/volumes/hoge-on-docker_postgres_data/_data",
        "Name": "hoge-on-docker_postgres_data",
        "Options": null,
        "Scope": "local"
    }
]

在app目录下直接添加entrypoint.sh

圈试点 t。嘘
#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

python manage.py flush --no-input
python manage.py migrate

exec "$@"

entrypoint.sh立即更改文件的执行权限

~/*$ chmod +x app/entrypoint.sh

修改 Dockerfile

Dockerfile
# pull official base image
FROM python:3.9.6-alpine

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install psycopg2 dependencies
RUN apk update \
    && apk add postgresql-dev gcc python3-dev musl-dev

# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt

# copy entrypoint.sh
COPY ./entrypoint.sh .
RUN sed -i 's/\r$//g' /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh

# copy project
COPY . .

# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

附加到 .env.dev

.恩诉在 v
DEBUG=1
SECRET_KEY=〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=hello_django_dev
SQL_USER=hello_django
SQL_PASSWORD=hello_django
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres

构建镜像并启动容器

~/*$ docker-compose up -d --build

如果您使用浏览器访问http://localhost:8000/ 并看到火箭,则可以。

写个便条它介绍了如何单独使用 Django 创建和启动容器。如果您在没有设置环境变量 DATABASE=postgres 的情况下进行构建,这是可能的。检查示例站点以了解如何编写命令。当然,使用这个执行时,settings.py 是准备 sqlite3 的形式。有没有一个场景你敢采用这样的启动方式?我现在想不出一个。不知从头开发时会不会有必要的场景?现在别担心,我们继续吧。

使用 Gunicorn 作为 nginx 和 Django 之间的联络人。添加到 requirements.txt。

要求.txt
django==4.1
gunicorn==20.1.0
psycopg2-binary==2.9.1

生产服务器是nginx,但是我想在开发的时候使用django内置的服务器。单独的 docker-compose 用于开发和生产。

为生产创建docker-compose.prod.yml。复制和更改docker-compose.yml

在生产环境中启动 gunicorn 而不是 runserver 在生产中,不需要将主机和容器(绑定挂载)与 web 容器链接,因此将其删除。

准备生产配置文件.env.prod。通过复制/更改开发配置文件创建.env.dev

将 DEBUG 从 1 更改为 0 将 SQL_DATABASE 更改为 hello_django_开发者来自 hello_django_产品改成

为生产数据库准备配置文件.env.prod.db

Docker-compose.yml 将生成 db 映像所需的 POSTGRES 环境变量(克隆后立即包含在 docker-compose.prod.yml 中)迁移到此 .env.prod.db。 (别忘了重写 _dev → _prod) 码头工人-compose.prod.yml
version: '3.8'

services:
  web:
    build: ./app
    command: gunicorn config.wsgi:application --bind 0.0.0.0:8000
    ports:
      - 8000:8000
    env_file:
      - ./.env.prod
    depends_on:
      - db
  db:
    image: postgres:13.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env.prod.db

volumes:
  postgres_data:
.恩诉产品
DEBUG=0
SECRET_KEY=〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=hello_django_prod
SQL_USER=hello_django
SQL_PASSWORD=hello_django
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres

.env.prod.db(数据库名称是_prod,而不是_dev。使用复制和粘贴时要小心)

.env.prod.db
POSTGRES_USER=hello_django
POSTGRES_PASSWORD=hello_django
POSTGRES_DB=hello_django_prod

删除容器(添加 -v 因为我们也想删除相关卷)

~/*$ docker-compose down -v

构建生产镜像并启动容器

~/*$ docker-compose -f docker-compose.prod.yml up -d --build

在浏览器中访问http://localhost:8000/admin,如果显示管理员管理登录屏幕,则可以。现在没有 CSS 装饰也没关系。以后如果静态文件的设置完成会改进。

如果它不起作用,请检查日志。请注意,如果未指定文件名,将读取 docker-compose.yml。当您要查看生产容器的详细信息时,不要忘记指定文件名-f docker-compose.prod.yml。

~/*$ docker-compose -f docker-compose.prod.yml logs -f

准备生产 Dockerfile。用目前Dockerfile和entrypoint.sh的组合,每次启动容器,

python manage.py flush --no-input  データベースのクリア
python manage.py migrate       マイグレート

会跑。这在开发过程中很好,但如果你在生产中这样做就不好了。迁移以“没有变化,所以不需要”结束,但是清库是个大问题。

直接在app下准备entrypoint.prod.sh

圈试点 t。 p 杆。嘘
#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

exec "$@"

更改文件的执行权限

~/*$ chmod +x app/entrypoint.prod.sh
准备 Dockerfile.prod

为了减少生产镜像的容量,它包括两个阶段,Builder和Final。使用多阶段构建方法。

建造者

安装运行 psycopg2 所需的应用程序。 安装并运行 flake8(lint) 以检查 Django 应用程序中的代码是否有任何问题。 Pip wheel ***** 构建安装 requirements.txt 软件包所需的轮组。有关制造车轮的优势和选择的描述,看

最后

安装 libpq(PostgreSQL 的 C 语言界面)。 Builder 中使用的 requirements.txt 和 Builder 构建的轮组的合并。使用此安装。 entrypoint.prod.sh 等的副本。 做 c 家庭文件。产品
###########
# BUILDER #
###########

# pull official base image
FROM python:3.9.6-alpine as builder

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install psycopg2 dependencies
RUN apk update \
    && apk add postgresql-dev gcc python3-dev musl-dev

# lint
RUN pip install --upgrade pip
RUN pip install flake8==3.9.2
COPY . .
RUN flake8 --ignore=E501,F401 .

# install dependencies
COPY ./requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt


#########
# FINAL #
#########

# pull official base image
FROM python:3.9.6-alpine

# create directory for the app user
RUN mkdir -p /home/app

# create the app user
RUN addgroup -S app && adduser -S app -G app

# create the appropriate directories
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

# install dependencies
RUN apk update && apk add libpq
COPY --from=builder /usr/src/app/wheels /wheels
COPY --from=builder /usr/src/app/requirements.txt .
RUN pip install --no-cache /wheels/*

# copy entrypoint.prod.sh
COPY ./entrypoint.prod.sh .
RUN sed -i 's/\r$//g'  $APP_HOME/entrypoint.prod.sh
RUN chmod +x  $APP_HOME/entrypoint.prod.sh

# copy project
COPY . $APP_HOME

# chown all the files to the app user
RUN chown -R app:app $APP_HOME

# change to the app user
USER app

# run entrypoint.prod.sh
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]

RUN sed **** 的作用sed 命令是“流编辑器”的缩写。根据命令处理指定文件。逐行读取输入,进行文本转换等编辑,逐行输出。支持正则表达式。

[参考]换行代码的变更

这次我想直接覆盖文件,所以用-i选项RUN sed -i 's/\r$//g' $APP_HOME/entrypoint.prod.sh和正则表达式部分是Docker学習、私はこう取り組んだ,我练习得还不够,所以我继续。

docker-compose.prod.yml 中的 web 现在改为 Dockerfile,因此将其改为 Dockerfile.prod。

docker-compose.prod.yml(仅针对网络发布)
web:
  build:
    context: ./app
    dockerfile: Dockerfile.prod
  command: gunicorn hello_django.wsgi:application --bind 0.0.0.0:8000
  ports:
    - 8000:8000
  env_file:
    - ./.env.prod
  depends_on:
    - db

我准备好了,让我们试试吧。清理它,构建它,然后运行它。

~/*$ docker-compose -f docker-compose.prod.yml down -v
~/*$ docker-compose -f docker-compose.prod.yml up -d --build

我想你会得到这样的错误。

executor failed running [/bin/sh -c flake8 --ignore=E501,F401 .]: exit code: 1
ERROR: Service 'web' failed to build : Build failed

flake8 是一个代码检查工具。看来Django自动生成的部分也有冲突。正如所料,我不知道,所以只检查了 config 的内部。Dockerfile.prodRUN flake8 --ignore=E501,F401 .的RUN flake8 --ignore=E501,F401 ./config改成。稍后,当您添加 Django 应用程序时,您也应该检查这些目录,但在您觉得需要之前,只需配置即可,然后继续。 (请不要模仿这种过分的态度Docker学習、私はこう取り組んだ

重建和迁移。需要10多分钟。长。 .

~/*$ docker-compose -f docker-compose.prod.yml up -d --build
~/*$ docker-compose -f docker-compose.prod.yml exec web python manage.py migrate --noinput

如果在浏览器中访问http://localhost:8000/admin显示就可以了。 (还没有 CSS)由于多阶段构建,图像的数据大小应该要小得多。 (我忘了记录之前的状态。)

介绍 Nginx添加到 docker-compose.prod.yml

添加 docker-compose.prod.yml
nginx:
  build: ./nginx
  ports:
    - 1337:80
  depends_on:
    - web

在项目根目录(即hoge-on-docker/)创建nginx目录,并在其下创建Dockerfile和nginx.conf。

Dockerfile
FROM nginx:1.21-alpine

RUN rm /etc/nginx/conf.dhttps://www.likecs.com/default.conf
COPY nginx.conf /etc/nginx/conf.d
nginx.conf
upstream config {
    server web:8000;
}

server {
    listen 80;
    location / {
        proxy_pass http://config;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }
}

摆弄docker-compose.prod.ymlweb 端口设置。我试图用ports连接到外面,但是通过nginx时,只有容器可以连接到web,所以改成expose。确保在某些时候您无法直接访问http://localhost:8000。

docker-compose.prod.yml 的变化
web:
  build:
    context: ./app
    dockerfile: Dockerfile.prod
  command: gunicorn hello_django.wsgi:application --bind 0.0.0.0:8000
  expose:
    - 8000
  env_file:
    - ./.env.prod
  depends_on:
    - db

操作检查

~/*$ docker-compose -f docker-compose.prod.yml down -v
~/*$ docker-compose -f docker-compose.prod.yml up -d --build
~/*$ docker-compose -f docker-compose.prod.yml exec web python manage.py migrate --noinput

在浏览器中访问http://localhost:1337/

Not Found
The requested resource was not found on this server.

如果显示确定。如果是http://localhost:1337/admin,则显示不带CSS的管理界面登录。

取下容器

~/*$ docker-compose -f docker-compose.prod.yml down -v

设置静态文件

在我们进入正题之前,不要忘记在 settings.py 中更改区域设置。

settings.py 中的更改
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'

接下来,更改/添加与静态文件相关的 settings.py

对 settings.py 的更改/添加
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"

有了这个开发模式(即当 DEBUG=1 时)然后当您访问http://localhost:8000/static/* 时,会搜索app/staticfiles/*。我还没有准备好静态文件目录。 .以python manage.py runserver 开头的 Django 内置服务器就是这样工作的。但是,在生产服务器上使用的nginx 必须手动设置。按顺序进行生产环境的设置。

码头工人-compose.prod.yml
version: '3.8'

services:
  web:
    build:
      context: ./app
      dockerfile: Dockerfile.prod
    command: gunicorn config.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - static_volume:/home/app/web/staticfiles
    expose:
      - 8000
    env_file:
      - ./.env.prod
    depends_on:
      - db
  db:
    image: postgres:13.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env.prod.db
  nginx:
    build: ./nginx
    volumes:
      - static_volume:/home/app/web/staticfiles
    ports:
      - 1337:80
    depends_on:
      - web

volumes:
  postgres_data:
  static_volume:

无法理解的笔记老实说,我不明白模型网站上的以下文字。如果您阅读链接到(来源)的常见问题解答,可能会令人耳目一新。我没有那么大的权力,所以我暂时搁置它。 .

为什么这是必要的?Docker Compose 通常以 root 身份挂载命名卷。由于我们使用的是非 root 用户,如果目录不存在,则在运行 collectstatic 命令时会收到权限被拒绝错误

要解决此问题,您可以:

在 Dockerfile 中创建文件夹 挂载后更改目录的权限我们使用了前者。

无法理解的笔记web 和 nginx

volumes:
  - static_volume:/home/app/web/staticfiles

无法自信地说你明白为什么会这样的状态。 .写下你目前的理解。

使用 collectstatic 收集和存储静态文件的目的地是 /home/app/web/staticfiles 的 web 容器。 相同的静态文件存储在由webvolumes: 链接的Docker 管理区域的static_volume 中。 nginx 转到nginx 容器的/home/app/web/staticfiles 以响应http://〇〇〇〇〇/static/* 的访问请求nginx.conf(稍后添加)。 nginx 的volumes: 与static_volume:/home/app/web/staticfiles 一样链接,因此从web 侧存储在static_volume 中的静态文件也将复制到nginx 侧的/home/app/web/staticfiles。 因此,静态文件存在于nginx 的/home/app/web/staticfiles 中并且可以显示。

我想知道是不是流量。

有些事情尚不清楚,但请相信示例并继续前进!

在 Dockerfile.prod 中添加一行来创建 staticfiles 目录

Dockerfile.prod 中的补充
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
RUN mkdir $APP_HOME/staticfiles
WORKDIR $APP_HOME

路由nginx查看静态文件

nginx.conf
upstream config {
    server web:8000;
}

server {
    listen 80;
    location / {
        proxy_pass http://config;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }

    location /static/ {
        alias /home/app/web/staticfiles/;
    }
}

运行检查开始

~/*$ docker-compose -f docker-compose.prod.yml up -d --build
由于粗心的错误导致的错误处理(我不认为每个人都会提出,所以请继续)

我有一个错误。

・・・・・・
 => CACHED [builder 5/9] RUN pip install flake8==3.9.2      0.0s
 => CANCELED [builder 6/9] COPY . .              2.5s
------
 > [stage-1  4/15] RUN mkdir /home/app/web/staticfiles:
#7 1.632 mkdir: can't create directory '/home/app/web/staticfiles': No such file or directory
------
executor failed running [/bin/sh -c mkdir $APP_HOME/staticfiles]: exit code: 1
ERROR: Service 'web' failed to build : Build failed

编辑docker-compose.prod.yml时,复制粘贴的位置出错,

docker-compose.prod.yml 的一部分(有错误)
RUN mkdir $APP_HOME/staticfiles
RUN mkdir $APP_HOME

就是这样。 .更换顶部和底部后,我能够正常构建。错误处理结束。

继续迁移

~/*$ docker-compose -f docker-compose.prod.yml exec web python manage.py migrate --noinput

如果执行collectstatic,会将多个静态目录的信息聚合(复制)到staticfiles目录。

~/*$ docker-compose -f docker-compose.prod.yml exec web python manage.py collectstatic --no-input --clear

让我们检查管理员管理屏幕。如果你访问http://localhost:1337/admin 和css装饰作品,你就成功了!

让我们把容器放下

~/*$ docker-compose -f docker-compose.prod.yml down -v

为了验证媒体文件的操作,您必须准备一个实际上传图像并显示图像的应用程序。使用绑定挂载设置构建开发模式,因为您希望在主机端反映在容器中编辑的内容。主机端是在 WSL2 Ubuntu 中创建的数据。

~/*$ docker-compose up -d --build

在 Web 容器中运行 Django startapp

~/*$ docker-compose exec web python manage.py startapp upload

这里如果host端的app目录下也生成了upload,说明bind mount正在工作。正如上面简要提到的,我遇到了一种绑定挂载根本不起作用的模式。我在另一台 PC 上重新创建了该项目,它运行良好,所以原因仍然未知。 .

与前面的示例相反,在主机端所做的更改也应该反映在容器中。在主机端 WSL2 Ubuntu 的 $~/works/hoge-on-docker/app/config/ 中更改并保存 settings.py。

settings.py 的一部分
INSTALLED_APPS = [
    ・・・・・・,
    ・・・,

    'upload',
]

覆盖保存。没问题。

接下来在容器端生成,并重写上传中反映到主机端的文件。

应用程序/上传/views.py
from django.shortcuts import render
from django.core.files.storage import FileSystemStorage

def image_upload(request):
    if request.method == "POST" and request.FILES["image_file"]:
        image_file = request.FILES["image_file"]
        fs = FileSystemStorage()
        filename = fs.save(image_file.name, image_file)
        image_url = fs.url(filename)
        print(image_url)
        return render(request, "upload.html", {
            "image_url": image_url
        })
    return render(request, "upload.html")

无法覆盖保存。 .我收到一条 VScode 错误消息。

'views.py' を保存できませんでした。
ファイル 'vscode-remote://wsl+ubuntu/home/●●●/works/hoge-on-docker/app/upload/views.py' を
書き込むことができません (NoPermissions (FileSystemError): 
Error: EACCES: permission denied, open '/home/●●●/works/hoge-on-docker/app/upload/views.py')

“将 Docker 与 WSL2 结合使用时解决权限问题的简单方法(使用 docker-compose.yml)”让我在本文中使用 WSL2 侧应对方法。

~/*$ sudo chown -R $USER:$USER .

您可以按重试按钮。如果没有响应,则表示文件已成功覆盖并保存。同时,这些变化也反映在容器方面。

接下来创建 app/upload/templates 目录并在那里创建 upload.html

上传.html
{% block content %}

  <form action="{% url "upload" %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="file" name="image_file">
    <input type="submit" value="submit" />
  </form>

  {% if image_url %}
    <p>File uploaded at: <a href="{{ image_url }}">{{ image_url }}</a></p>
  {% endif %}

{% endblock %}

应用程序/配置/urls.py
from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static

from upload.views import image_upload

urlpatterns = [
    path("", image_upload, name="upload"),
    path("admin/", admin.site.urls),
]

if bool(settings.DEBUG):
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

settings.py 的一部分
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "mediafiles"

(我可能错过了一份工作备忘录。)如果在host端新建文件,应该是和container端权限不匹配,所以再次在这个阶段,

~/*$ sudo chown -R $USER:$USER .

你不必这样做吗?

试驾一下。

~/*$ docker-compose up -d --build

在浏览器中访问http://localhost:8000/。准备一张图片,选择一个文件并提交。如果您可以通过踩到显示的链接来显示图像,那就可以了。

由于到目前为止我们一直在开发模式下进行,因此我们还将在生产环境方面进行更改。添加到 docker-compose.prod.yml 中的 web 和 nginx 卷

码头工人-compose.prod.yml
version: '3.8'

services:
  web:
    build:
      context: ./app
      dockerfile: Dockerfile.prod
    command: gunicorn config.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - static_volume:/home/app/web/staticfiles
      - media_volume:/home/app/web/mediafiles
    expose:
      - 8000
    env_file:
      - ./.env.prod
    depends_on:
      - db
  db:
    image: postgres:13.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env.prod.db
  nginx:
    build: ./nginx
    volumes:
      - static_volume:/home/app/web/staticfiles
      - media_volume:/home/app/web/mediafiles
    ports:
      - 1337:80
    depends_on:
      - web

volumes:
  postgres_data:
  static_volume:
  media_volume:
Dockerfile.prod 的一部分
# create the appropriate directories
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
RUN mkdir $APP_HOME/staticfiles
RUN mkdir $APP_HOME/mediafiles
WORKDIR $APP_HOME

nginx.conf
upstream config {
    server web:8000;
}

server {
    listen 80;
    location / {
        proxy_pass http://config;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }

    location /static/ {
        alias /home/app/web/staticfiles/;
    }

    location /media/ {
        alias /home/app/web/mediafiles/;
    }
}

开发模式下的容器

~/*$ docker-compose down -v

构建生产容器

~/*$ docker-compose -f docker-compose.prod.yml up -d --build
错误处理(如果没有,继续下一步)
 => [builder 6/9] COPY . .                                            3.6s
 => ERROR [builder 7/9] RUN flake8 --ignore=E501,F401 ./config        3.9s
------
 > [builder 7/9] RUN flake8 --ignore=E501,F401 ./config:
#18 2.898 ./config/urls.py:14:81: W292 no newline at end of file
------
executor failed running [/bin/sh -c flake8 --ignore=E501,F401 ./config]: exit code: 1
ERROR: Service 'web' failed to build : Build failed

从 flake8 开始,urls.py 的结尾因为没有换行而生气。复制时要小心。即使添加了最后一行,有选项卡的状态也没有用。将最后一行留空。我重建并通过了。

其次是迁移和收集静态。

~/*$ docker-compose -f docker-compose.prod.yml exec web python manage.py migrate --noinput
~/*$ docker-compose -f docker-compose.prod.yml exec web python manage.py collectstatic --no-input --clear

构建通过,可以访问http://localhost:1337/,但是选择图片文件后,点击图片展示页面的链接时出错

Forbidden (403)
CSRF verification failed. Request aborted.

More information is available with DEBUG=True.

从 Django4 (4.1?) 开始,您必须将 CSRF_TRUSTED_ORIGINS 添加到 settings.py。

settings.py 中的附加行
CSRF_TRUSTED_ORIGINS = ['http://localhost:1337',]

重建。 . (后来:我应该设置 DEBUG=1 来检查错误的详细信息)

还有片状8

 => [builder 6/9] COPY . .                                                          2.6s
 => ERROR [builder 7/9] RUN flake8 --ignore=E501,F401 ./config                      4.3s
------
 > [builder 7/9] RUN flake8 --ignore=E501,F401 ./config:
#18 3.614 ./config/settings.py:134:48: E231 missing whitespace after ','
------
executor failed running [/bin/sh -c flake8 --ignore=E501,F401 ./config]: exit code: 1
ERROR: Service 'web' failed to build : Build failed

missing whitespace after ',' 津贴。很麻烦。 .

对 settings.py 的小修改(在 , 之后添加半角空格)
CSRF_TRUSTED_ORIGINS = ['http://localhost:1337', ]

这次!

~/*$ docker-compose -f docker-compose.prod.yml up -d --build
~/*$ docker-compose -f docker-compose.prod.yml exec web python manage.py migrate --noinput
~/*$ docker-compose -f docker-compose.prod.yml exec web python manage.py collectstatic --no-input --clear

做到了。模型网站说上传文件的大小限制是现在的 1MB。更改 nginx.conf。

nginx.conf 的一部分
location / {
    proxy_pass http://hello_django;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_redirect off;
    client_max_body_size 100M;
}

这是可以在模型站点上完成的操作的结束。

SSL的方法介绍了,但是我觉得不可能,所以放弃了。作为调查的结果,我们认为 https-portal 更好。

在最后

在写这篇文章的时候,我发现一个搜索结果是“Tutorial for Understanding Docker images”。非常。让我学习。下次我们将添加带有 SSL 的 https-portal。当我感觉好些时我会写。

原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308626069.html

107人参与, 0条评论 登录后显示评论回复

你需要登录后才能评论 登录/ 注册