

最近我做了一个 哔哩哔哩直播弹幕姬 ↗ 项目,为了让大家能更方便地使用,我决定将这个项目容器化,直接用 Docker 一键启动。这样,别人就不用担心配置环境了,直接运行就好。
如果你对 Docker 还不太熟悉,它其实就是一个让你把应用和所有的依赖打包在一起的工具,确保在任何机器上都能以相同的方式运行。通过 Docker,我能把项目打包成容器,避免了不同环境配置不一致的问题。
接下来,我会一步步带你走过:
- 如何写 Dockerfile 来创建镜像;
- 用 docker-compose.yml 来管理多个容器;
- 怎么构建并启动 Docker 容器;
- 容器里的应用怎么配置和运行;
- 如果需要扩展容器环境,应该怎么做。
不管你是刚接触 Docker 还是已经有点经验,相信这篇教程能帮你更好地理解 Docker,并能把自己的项目轻松容器化。
创建 Dockerfile#
Dockerfile 是一个文本文件,包含了一系列的指令,Docker 使用这些指令来构建镜像。你可以通过它指定操作系统、安装依赖、复制文件、设置环境变量等。
示例 Dockerfile
FROM php:8.2-cli-alpine
# 安装 Composer
COPY --from=composer:2.7 /usr/bin/composer /usr/bin/composer
# 设置环境变量
ENV TZ=Asia/Shanghai
# 更新软件包列表并安装系统依赖
RUN apk update && apk add --no-cache \
bash \
git \
curl \
brotli \
build-base \
autoconf \
libtool \
make \
linux-headers \
pcre-dev \
libevent \
libevent-dev \
libpng-dev \
libjpeg-turbo-dev \
libwebp-dev \
freetype-dev \
$PHPIZE_DEPS \
redis \
busybox-suid # 添加 cron 支持
# 安装 PHP 扩展
RUN docker-php-ext-install pdo_mysql pcntl
# 安装 PHP GD 扩展
RUN docker-php-ext-configure gd \
--with-jpeg \
--with-webp \
--with-freetype \
&& docker-php-ext-install gd
# 安装 PHP Redis 扩展
RUN pecl install redis \
&& docker-php-ext-enable redis
# 安装 PHP Brotli 扩展
RUN pecl install brotli \
&& docker-php-ext-enable brotli
# 设置工作目录
WORKDIR /var/www/bilibili_danmu
# 复制项目文件到容器中
RUN git clone https://github.com/zxc7563598/php-bilibili-danmu.git /var/www/bilibili_danmu
# 安装 PHP 依赖(生产环境中使用 --no-dev)
RUN composer install
# 设置目录权限
RUN chmod +x /var/www/bilibili_danmu
# 添加 cron 任务
RUN echo "0 * * * * /var/www/bilibili_danmu/check_and_update.sh" > /etc/crontabs/root
dockerfile说明: FROM:指定基础镜像。 RUN:安装依赖和 PHP 扩展。 COPY:将本地文件复制到容器中。 WORKDIR:设置工作目录。 CMD:容器启动时执行的命令。
创建 Docker Compose 文件#
docker-compose.yml 文件定义了多个容器的服务、网络和卷。它让我们可以一键启动多个容器,而不需要手动启动每个容器。
示例 docker-compose.yml
services:
php:
build: .
container_name: php
command: sh -c "sh setup.sh && php start.php start -d && crond && tail -f /dev/null"
volumes:
- /var/www/bilibili_danmu
networks:
- webnet
expose:
- '7776'
nginx:
image: nginx:latest
container_name: nginx
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
- .:/var/www/bilibili_danmu
ports:
- '7777:80'
networks:
- webnet
depends_on:
- php
redis:
image: redis:latest
container_name: redis
ports:
- '6379'
networks:
- webnet
networks:
webnet:
driver: bridge
yml在上述文件中,定义了三个服务:php、nginx 和 redis,并配置了它们如何协同工作:
PHP 服务:运行应用代码并启动 PHP 和 cron 服务。
Nginx 服务:提供 Web 访问,使用自定义配置文件。
Redis 服务:提供缓存支持。
所有这些服务都连接到同一个自定义网络 webnet,确保它们能够顺畅地通信。
可以通过运行 docker-compose up -d 来启动这些服务,并在浏览器中访问 Nginx 提供的 Web 服务。
PHP 服务#
php:
build: .
container_name: php
command: sh -c "sh setup.sh && php start.php start -d && crond && tail -f /dev/null"
volumes:
- /var/www/bilibili_danmu
networks:
- webnet
expose:
- '7776'
yml- build: .:这行代码表示 Docker 会在当前目录下查找 Dockerfile 并基于它构建 PHP 镜像。这个镜像包含了运行 PHP 应用所需的所有依赖和配置。
- container_name: php:为这个容器指定一个名字,便于我们在 Docker 中识别和管理。
- command: sh -c “sh setup.sh && php start.php start -d && crond && tail -f /dev/null”:这行命令会在容器启动时执行。首先,它会运行 setup.sh 脚本,接着启动 PHP 应用(start.php start -d),然后启动 cron 服务(crond),最后使用 tail -f /dev/null 保持容器处于运行状态,防止容器因任务执行完毕而停止。
- volumes:
volumes:
- /var/www/bilibili_danmu
yml这行代码将宿主机的 /var/www/bilibili_danmu 目录挂载到容器内部的 /var/www/bilibili_danmu 目录。这确保了 PHP 容器能够访问和处理项目代码。
- networks:
networks:
- webnet
yml容器会连接到一个名为 webnet 的网络,这个网络在文件底部定义。
- expose:
expose:
- '7776'
ymlexpose 命令暴露容器的 7776 端口,供其他容器(如 Nginx)访问。需要注意的是,expose 并不会将端口映射到宿主机,只是让其他容器可以通过这个端口访问。
Nginx 服务#
nginx:
image: nginx:latest
container_name: nginx
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
- .:/var/www/bilibili_danmu
ports:
- '7777:80'
networks:
- webnet
depends_on:
- php
yml-
image: nginx:latest: 使用官方的 Nginx 镜像,并始终拉取最新版本。
-
container_name: nginx:
为 Nginx 容器指定一个名字,便于识别。
- volumes:
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
- .:/var/www/bilibili_danmu
yml这两个挂载使得宿主机的 ./nginx/default.conf 配置文件和整个项目目录能够映射到容器内。这样,Nginx 容器就能使用项目的代码和自定义的配置文件。
- ports:
ports:
- '7777:80'
yml这行代码将容器的 80 端口映射到宿主机的 7777 端口,允许外部访问 Nginx 服务。
- networks:
networks:
- webnet
ymlNginx 服务也连接到 webnet 网络,以便和其他容器通信。
- depends_on:
depends_on:
- php
yml这表示 Nginx 容器在启动时依赖于 php 容器。depends_on 确保 PHP 容器先启动,以便 Nginx 容器能够访问它。
Redis 服务#
redis:
image: redis:latest
container_name: redis
ports:
- '6379'
networks:
- webnet
ymlimage: redis:latest: 使用官方 Redis 镜像,拉取最新版本。
container_name: redis: 为 Redis 容器指定一个名字,便于管理和识别。
ports:
ports:
- '6379'
yml将 Redis 的默认端口 6379 暴露到宿主机上,允许外部程序与 Redis 通信。
networks:
networks:
- webnet
ymlRedis 容器连接到 webnet 网络,确保它与 PHP 和 Nginx 容器能够通信。
自定义网络定义#
networks:
webnet:
driver: bridge
ymlnetworks 定义了一个名为 webnet 的网络,所有容器都将连接到这个网络。通过这种方式,容器间可以互相通信,并且不会暴露给外部世界,除非明确映射端口。这里使用了 bridge 网络驱动,这是 Docker 默认的网络类型,适合容器之间的通信。
构建和启动容器#
- 构建 Docker 镜像: 在包含 Dockerfile 与 docker-compose.yml 的目录下运行以下命令构建镜像:
docker-compose build
shell- 启动 Docker Compose 服务: 在包含 Dockerfile 与 docker-compose.yml 的目录下运行:
docker-compose up -d
shell这条命令会构建和启动所有定义的服务。-d 参数表示在后台运行。
- 查看容器状态: 使用以下命令查看运行中的容器:
docker ps
shell- 停止容器: 要停止容器,运行以下命令:
docker-compose down
shell其他常用命令#
- 查看容器日志:
docker logs <container_name_or_id>
bash- 进入容器的终端:
docker exec -it <container_name_or_id> sh
bash- 删除容器和镜像: 停止并删除所有容器和镜像:
docker-compose down --rmi all
bash- 删除不再使用的资源
以下内容均会被删除:
- 所有未被任何容器使用的镜像(dangling images)
- 所有停止的容器(stopped containers)
- 所有未被使用的网络(unused networks)
- 所有未被使用的卷(未使用的匿名卷,需加 —volumes 才会删除)
- 所有未使用的构建缓存
docker system prune
bash