预备知识
- Docker 是什么
- Docker 镜像是什么
- Docker 容器是什么
- Docker Compose 是什么
- Docker Compose 中的 Service 是什么
请自行上网查阅以上内容相关资料,否则无法阅读下文
安装 Docker
Windows
去官网 Docker: Accelerated Container Application Development 下载并安装。安装完成之后会提示重启。通常情况下正常重启就行。但我一开始试的那台电脑装了 Windows 和黑苹果双系统,在开机的时候会提示选择那个系统。结果试了好几次电脑都没法正常启动,我甚至一度以为是电脑坏了。最后进入 BIOS 把首选的启动选项从双系统选择器改为 Windows 自带的启动器,这样在重启的时候会直接进入 Windows,终于成功。
docker 运行的底层系统需要是 Linux,Windows10 之后的版本支持在 Windows 内运行 Linux,也就是所谓的 wsl。但大部分的系统本身的 wsl 版本太老,当你打开 docker 的时候也会出现提示。因此在第一次启动 docker 时,需要在终端执行:
wsl --update
更新 wsl 才行。
docker 默认的镜像存储空间是在 C 盘,之后随着使用过程中镜像数量的增多,占据的空间会越来越大。C 盘空间紧张的同学可以手动修改镜像存储空间。
点击右上角的齿轮-Resources-Advance 中就可以修改镜像的默认存储位置。
Mac
同样去官网下载并安装即可,不需要执行 wsl --update 过程。
部署 MySQL
为了简单起见,先尝试部署一个 MySQL 容器。MySQL 已经提供了官方的镜像,直接根据该镜像创建容器即可。
执行以下命令即可部署一个最基本的 MySQL 容器:
docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d --restart always mysql:5.7
- -p:端口映射。:左边的是宿主机(本机)端口,右边的是容器内端口。3306:3306 就是将容器内的 3306 端口映射到宿主机的 3306 端口。如果本机已经部署了在本地运行的 MySQL 服务(默认的端口就是 3306),那么就会冲突。这时候可以改成 3406:3306 或者任意空闲的本机端口。
- --name:这是给运行的容器起的名字,用于之后重启/停止/删除容器用
- -e:这是容器内的一些环境变量,这里设定了 root 用户的密码是 123456
- -d:代表在后台运行容器
- --restart:代表重启 Docker 服务后该容器是否重启。always 代表每次重启 Docker 服务后该容器也会重启。这样,只要设定 Docker 服务开机自启,那么这个 MySQL 容器也会开机启动,就像部署在本地的 MySQL 服务一样
- mysql:5.7:这是容器使用的镜像名称和标签,标签通常使用版本号来填写。mysql:5.7 就代表 5.7 版本的 MySQL 镜像
启动后,尝试使用 Navicat 等数据库管理工具连接,用户名 root,密码 123456,就可以成功连接到 Docker 内部署的 MySQL 容器,之后的使用方法和本地部署的 MySQL 无异。
查看 Docker 容器
执行 docker ps
命令可以查看正在运行的 Docker 容器,行 docker ps -a
命令可以查看所有 Docker 容器,显示的信息类似下面这样
如果想要停止一个容器,可以执行 docker stop 容器ID或容器名
。容器 ID 就是图中的 CONTAINER ID,容器名就是图中的 NAMES
如果想要删除一个容器,可以执行 docker rm 容器ID或容器名
查看 Docker 镜像
执行 docker images
命令可以查看本地已存在的镜像。如图
如果想要删除一个镜像,首先需要确保该镜像没有被任何容器使用,即便是已经停止的容器也不行。确认完毕之后可以执行 docker rmi 镜像ID或镜像名:镜像标签
来删除。实际操作中,镜像 ID 可以不填完整,只要填前几个能够和其他镜像区分开来的字符即可。
部署 Django 后端应用
为了部署 Django 应用,我们需要首先打包出自己的镜像,之后再使用该镜像创建容器。
在 Django 项目的工作目录下,创建名为 Dockerfile
的文件,其中的内容为:
# 使用官方的 Python 镜像作为基础镜像
FROM python:3.10.4
# 设置工作目录
WORKDIR /app
# 设置 pip 使用清华源
ENV PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
# 将当前目录下的所有文件复制到工作目录
COPY . /app/
# 安装项目所需的依赖
RUN pip install -r requirements.txt
# 将容器内的端口暴露出来,这里使用 Django 默认的端口 8000
EXPOSE 8000
# 启动 Django 项目
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
之后,在同个目录下执行:
docker build -t my-django-app .
这样就可以打包出名为 my-django-app 的镜像。最后的 .
代表读取当前目录下的 Dockerfile 文件来构建镜像
之后再运行
docker run -p 8000:8000 --name django-app my-django-app
我这里没有写-d,就是为了可以看到 Django 的启动过程
使用 docker compose 同时部署后端应用和 MySQL 数据库,并使两者能够连接
当一个应用包含多个容器时,就需要使用 Docker compose 来进行组织和管理。我们安装 Docker 时,通常情况下默认也安装了 Docker compose。
首先我们为了确保 Django 应用能够连上 MySQL,需要去 settings.py 文件中修改数据库连接配置,参考以下内容:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 默认
'NAME': 'mydb', # 连接的数据库名
'HOST': 'database', # mysql的地址
'PORT': 3306, # mysql的端口
'USER': 'root', # mysql的用户名
'PASSWORD': '123456' # mysql的密码
}
}
重点就在 HOST 和 NAME,需要和之后创建的 docker-compose.yml
中一致。HOST 对应 service 的名称,NAME 对应 MYSQL_DATABASE 这个环境变量。
之后创建一个 docker-compose.yml
文件,可以在任意目录下,但推荐和 Dockerfile 在同个目录下。
文件内容如下:
version: '3'
services:
database:
image: mysql:5.7
container_name: mysql
ports:
- "3306:3306"
volumes:
- ./mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: mydb
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
web:
image: my-django-app
container_name: django-app
command: bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
ports:
- "8000:8000"
depends_on:
- database
之后执行 docker-compose up -d
命令可以创建容器并运行(-d 代表后台运行),在这里会同时启动 Django 和 MySQL 容器,并且可以将 Django 中定义的数据库模型迁移到 MySQL 数据库上。如果想要停止并删除上述容器,就执行 docker-compose down
命令。如果不想删除容器,只想停止,就执行 docker-compose stop
命令,之后如果又想开始,可以执行 docker-compose start
命令。
上面这个文件中有一个注意点就是在 web 这个 service 下,加了一个 depends_on 参数,代表该 service 依赖于上面的 database。即首先得创建数据库容器,之后才能启动后端服务容器。
但在我的实际操作中,发现 MySQL 容器实际上在刚创建完成时还不能马上提供连接服务,而这个时候 Docker compose 以为 MySQL 服务已经就绪,就会启动 Django 服务并连接数据库,最终的结果是 Django 服务无法连上数据库导致启动失败。
为了避免上述情况的发生,更稳妥的方案是分别启动 MySQL 服务和 Django 服务,在确保 MySQL 服务就绪的情况下,再启动 Django。
为此,首先需要创建一个 Docker 网络,并在之后将两个容器放到同一个网络下使得它们可以连接。创建网络的命令为
docker network create app_net
之后,需要创建两个 docker-compose.yml 文件,用于分别启动 MySQL 和 Django。
第一个文件定义 MySQL 启动配置
version: '3'
networks:
custom_app_net:
name: app_net
external: true
services:
database:
image: mysql:5.7
container_name: mysql
ports:
- "3306:3306"
volumes:
- ./mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: mydb
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
networks:
- custom_app_net
执行 docker-compose up -d
命令后,确保 MySQL 服务启动成功后,再启动 Django 服务,对应的 docker-compose.yml 文件为:
version: '3'
networks:
custom_app_net:
name: app_net
external: true
services:
web:
image: my-django-app
container_name: django-app
command: bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
ports:
- "8000:8000"
depends_on:
- database
networks:
- custom_app_net
再执行 docker-compose up -d
来启动 Django 服务。这样就可以避免 MySQL 还未就绪就被 Django 抢连的情况。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于