一文说清docker及docker compose的应用和部署

前言

在当今复杂多变的软件开发与部署环境中,如何高效管理应用及其依赖,成为开发者们面临的一大挑战。你是否正为应用在不同环境中出现的兼容性问题而烦恼?是否渴望找到一种简便、快捷且可靠的方式来部署和运行项目?今天,我们将通过这篇文章,为你打开一扇新世界的大门,一文说清 docker 及 docker compose 的应用和部署,让你轻松应对这些难题,大幅提升开发与运维的效率。

假设现在服务器上需要部署三个项目,项目ABC,他们的web服务都是nginx,但是PHP版本不同,mysql数据库的版本也不相同,在传统模式下,尽管PHP可以多版本互存,但是数据库的多版本互存,相对来说就困难一些,在这种情况下,docker就是一种很好的解决方案。

docker主要由镜像和容器两部分组成,镜像可以理解成是一个模板,那么容器就是根据镜像,创建的不同的可执行的实例,那么这些实例之间是相互独立的。

一、Docker 的安装

1.1 安装 docker

安装过程中,可能因网络问题导致中断。若出现这种情况,重新执行安装命令即可继续。安装成功后,可查看对应的版本,若能显示版本信息,便证明安装已完成。

# 安装 Docker 所需的依赖
yum install -y yum-utils device-mapper-persistent-data lvm2

# 添加 Docker 的 yum 源
yum-config-manager --add-repo https://mirrors.cloud.tencent.com/docker-ce/linux/centos/docker-ce.repo

# yum 安装 Docker
yum install -y docker-ce docker-ce-cli containerd.io

# 查看 Docker 版本
docker version

安装docker过程

1.2 启动 docker

启动docker,并将其设置为开机自启动,随后查看运行状态。当状态显示为active (running)时,表明docker正在运行。

# 执行以下命令启动 Docker
systemctl start docker

# 然后将 Docker 设置为开机启动
systemctl enable docker

# 查看 Docker 运行状态
service docker status

# 可能返回以下内容,看到 active (running) 表示正在运行中
Redirecting to /bin/systemctl status docker.service
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2023-12-22 10:00:56 CST; 11s ago
     Docs: https://docs.docker.com

启动docker过程

1.3 配置 docker 镜像加速

由于docker的镜像服务器位于海外,国内访问速度相对较慢。为提升访问效率,可将镜像源设置为国内的加速镜像,此处以腾讯云的镜像加速服务为例。配置完成后,需重启相关服务以使设置生效。

方法一:

# 创建Docker配置目录
mkdir -p /etc/docker

#配置Docker镜像加速源
vim /etc/docker/daemon.json

#输入以下内容后保存退出
{
  "registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}

#重启守护进程并重启Docker
systemctl daemon-reload && systemctl restart docker

方法二:

sudo su -
cat >> /etc/docker/daemon.json <<- EOF
{
  "registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
EOF

systemctl daemon-reload && systemctl restart docker

配置docker镜像加速过程

1.4 体验 docker

完成上述设置后,即可着手体验docker的基本功能。借助简单的命令,便能轻松完成镜像的拉取与容器的创建。在此,我们以拉取nginx镜像并创建容器为例。容器创建成功后,随即可以运行。此时,通过服务器的IP地址,即可访问nginx的默认页面,这表明nginx已成功部署。

#拉取最新的nginx镜像
docker pull nginx

#运行容器
docker run -d --name nginx -p 80:80 nginx

#查看容器
docker ps -a

#显示结果
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                               NAMES
cc5b9ffeb31d   nginx     "/docker-entrypoint.…"   6 seconds ago   Up 5 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   nginx

体验docker过程

二、Docker 的镜像与容器

Docker镜像本质上是一种只读模板,它包含了运行应用程序所需的一切,如代码、运行时环境、库文件等。

Docker容器则是基于镜像创建的运行实例。一个镜像能够创建多个相互独立的容器,这些容器在各自的隔离环境中运行,彼此之间互不干扰。

镜像与容器是docker的核心概念。在前面的操作中,我们拉取的nginx镜像就是一个只读模板,而基于该镜像创建的nginx容器,则是一个可以独立运行的实例。

三、Docker 容器的独立性

项目 web服务 php版本 mysql版本
项目A nginx php7.4 mysql5.7
项目B nginx php8.0 mysql8.0
项目C nginx php7.4 mysql8.0

鉴于docker的独立性优势,在面对如上述表格所示的复杂部署环境时,我们可以通过拉取不同的镜像,如不同版本的nginx、PHP以及mysql数据库镜像,分别创建对应的容器。每个容器都能在各自独立的环境中运行,从而轻松满足不同项目对于软件版本的多样化需求。

四、操作示例

4.1 部署思路

本示例的部署思路为:分别拉取nginx、php7.4、php8.0、mysql5.7、mysql8.0镜像,进而创建不同的容器,搭建两套不同的LNMP环境:

  • LNMP_a:由nginx + php7.4 + mysql5.7组合而成。
  • LNMP_b:由nginx + php8.0 + mysql8.0组合而成。

4.2 拉取镜像

为演示搭建两套不同的LNMP环境,先构建第一套环境(nginx+PHP 7.4+mysql 5.7)。首要步骤是将所需镜像全部拉取下来,随后查看当前已拉取到本地的所有镜像。

# 拉取镜像
docker pull nginx
docker pull php:7.4-fpm
docker pull php:8.0-fpm
docker pull mysql:5.7
docker pull mysql:8.0

# 查看镜像
docker images

拉取镜像过程

4.3 部署LNMP_a

依据LNMP_a(nginx + php7.4 + mysql5.7)的环境要求,按以下命令依次执行,将顺序创建数据库、PHP以及nginx的容器,并完成相关配置。

# 建立lnma_a项目的各功能目录
mkdir -p ~/lnmp_a/{www,nginx,mysql}

# 建立网络
docker network create network_a

# mysql容器
docker run -d --name mysql57_a \
  -p 33061:3306 \
  -v ~/lnmp_a/mysql:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=root_password \
  --network network_a \
  mysql:5.7

# php容器
docker run -d --name php74_a \
  -v ~/lnmp_a/www:/var/www/html \
  --network network_a \
  php:7.4-fpm

# nginx conf配置文件
vim ~/lnmp_a/nginx/default.conf

########## 将下方内容复制至配置文件内 ##########
server {
    listen 80;
    server_name localhost;
    root /var/www/html;

    location / {
        index index.php index.html;
    }

    location ~ \.php$ {
        fastcgi_pass php74_a:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
########## 将上方内容复制至配置文件内 ##########

# nginx容器
docker run -d --name nginx_a \
  -p 8081:80 \
  -v ~/lnmp_a/www:/var/www/html \
  -v ~/lnmp_a/nginx/default.conf:/etc/nginx/conf.d/default.conf \
  --network network_a \
  nginx:latest

部署LNMP_a过程

4.3.1 镜像容器说明

执行docker ps -a命令查看容器。其中,第一个nginx容器是前期体验时创建的;而后续名称中带有下划线“_a”的三个容器,则是为创建第一个项目(LNMP_a)所生成。这三个容器的数据相互独立,并且此nginx容器与最初体验时创建的nginx容器彼此互不干扰。

LNMP_a镜像容器查看

4.3.2 测试文件说明

为检验容器能否正常工作,创建一个静态文件和一个动态PHP文件进行测试。

访问静态文件时,页面显示“hello lnmp_a”,表明静态文件可正常解析。

访问PHP文件时,呈现phpinfo信息,显示当前PHP的相关信息,说明PHP动态解析功能也已实现。

# 建立网站静态文件
vim ~/lnmp_a/www/index.html
# 内容
hello lnmp_a

# 建立网站php文件
vim ~/lnmp_a/www/index.php
# 内容
<?php
phpinfo();

LNMP_a测试文件访问

4.3.3 数据库测试说明

同时对数据库进行测试,新建一个数据库,检查数据库能否正常创建,以及对应文件夹中是否显示新建的数据库文件。

# 创建数据库
docker exec -it mysql57_a mysql -uroot -proot_password
CREATE DATABASE IF NOT EXISTS docker_mysql57_db;
SHOW DATABASES;
exit;

# 查看数据库文件
ls ~/lnmp_a/mysql/

4.4 部署LNMP_b

构建LNMP_b环境(nginx + php8.0 + mysql8.0),执行如下命令:

# 建立lnma_b项目的各功能目录
mkdir -p ~/lnmp_b/{www,nginx,mysql}

# 建立网络
docker network create network_b

# mysql容器
docker run -d --name mysql80_b \
  -p 33062:3306 \
  -v ~/lnmp_b/mysql:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=root_password \
  --network network_b \
  mysql:8.0

# php容器
docker run -d --name php80_b \
  -v ~/lnmp_b/www:/var/www/html \
  --network network_b \
  php:8.0-fpm

# nginx conf配置文件
vim ~/lnmp_b/nginx/default.conf

########## 将下方内容复制至配置文件内 ##########
server {
    listen 80;
    server_name localhost;
    root /var/www/html;

    location / {
        index index.php index.html;
    }

    location ~ \.php$ {
        fastcgi_pass php80_b:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
########## 将上方内容复制至配置文件内 ##########

# nginx容器
docker run -d --name nginx_b \
  -p 8082:80 \
  -v ~/lnmp_b/www:/var/www/html \
  -v ~/lnmp_b/nginx/default.conf:/etc/nginx/conf.d/default.conf \
  --network network_b \
  nginx:latest

# 建立网站静态文件
vim ~/lnmp_b/www/index.html
# 内容
hello lnmp_b

# 建立网站php文件
vim ~/lnmp_b/www/index.php
# 内容
<?php
phpinfo();

# 创建数据库
docker exec -it mysql80_b mysql -uroot -proot_password
CREATE DATABASE IF NOT EXISTS docker_mysql80_db;
SHOW DATABASES;
exit;

# 查看数据库文件
ls ~/lnmp_b/mysql/

4.4.1 创建过程及测试说明

采用与LNMP_a相同的方式,构建第二个项目(LNMP_b)所需的各类环境容器,并对其进行静态文件、PHP动态文件的访问测试,以及数据库测试。

4.4.2 镜像与容器说明

通过命令查看当前服务器上已创建好的容器,可发现容器主要分为3组:

  • 第一组仅有一个nginx容器,是最初体验时创建的。
  • 第二组容器名称带有下划线“_a”,属于第一个项目(LNMP_a)的3个容器。
  • 第三组容器名称带有下划线“_b”,属于第二个项目(LNMP_b)的3个容器。

这些容器相互独立、互不干扰。使用8081端口可访问第一个项目页面,使用8082端口可访问第二个项目页面。借助这种方式,在同一服务器上能够创建多个相互隔离的容器环境。

LNMP_b及整体容器查看

4.5 主要命令功能说明

4.5.1 创建功能模块目录

第一个命令用于创建各功能模块的目录:

  • www 目录存放程序和网页文件。
  • nginx 目录存放 Nginx 配置文件。
  • mysql 目录存放数据库文件。

命令使用 mkdir -p 递归创建目录,确保即使父目录不存在,也能顺利生成。

# 创建 lnmp_b 项目的目录结构
mkdir -p ~/lnmp_b/{www,nginx,mysql}

4.5.2 创建网络

为了让容器之间可以相互通信,需要先创建一个 Docker 网络。这样,处于同一网络的容器可以自动发现彼此,便于后续服务协同工作。

# 创建 Docker 网络
docker network create network_b

4.5.3 启动数据库容器

下面的命令用于启动 MySQL 容器,其中:

  • -d 让容器在后台运行,不影响终端操作。
  • --name 指定容器名称,方便管理。
  • -p 将主机的 33062 端口映射到容器的 3306 端口,供外部访问数据库。
  • -v 挂载本机 ~/lnmp_b/mysql 目录到容器内,实现数据持久化,避免容器删除后数据丢失。
  • -e 设定 root 用户的初始密码。
# 启动 MySQL 容器
docker run -d --name mysql80_b \
  -p 33062:3306 \
  -v ~/lnmp_b/mysql:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=root_password \
  --network network_b \
  mysql:8.0

4.5.4 启动 PHP 容器

PHP 容器用于处理动态网页,其关键参数:

  • -v 挂载 ~/lnmp_b/www 目录到 /var/www/html,让 PHP 代码能够在容器内运行。
  • --network 让 PHP 容器加入 network_b 网络,与其他容器互通。
# 启动 PHP 容器
docker run -d --name php80_b \
  -v ~/lnmp_b/www:/var/www/html \
  --network network_b \
  php:8.0-fpm

4.5.5 配置 Nginx

接下来,需要创建 Nginx 配置文件,让其能正确解析 PHP 请求。

# 创建并编辑 Nginx 配置文件
vim ~/lnmp_b/nginx/default.conf

然后将以下内容粘贴到 default.conf 文件中:

server {
    listen 80;
    server_name localhost;
    root /var/www/html;

    location / {
        index index.php index.html;
    }

    location ~ \.php$ {
        fastcgi_pass php80_b:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

4.5.6 启动 Nginx 容器

最后,运行 Nginx 容器,使其能够解析网页并将 PHP 请求转发给 PHP 容器。

  • -p 将主机 8082 端口映射到容器的 80 端口,供外部访问网站。
  • -v 绑定 ~/lnmp_b/www 目录,使网页文件可被访问。
  • -v 挂载 Nginx 配置文件,确保容器内使用我们定义的规则。
# 启动 Nginx 容器
docker run -d --name nginx_b \
  -p 8082:80 \
  -v ~/lnmp_b/www:/var/www/html \
  -v ~/lnmp_b/nginx/default.conf:/etc/nginx/conf.d/default.conf \
  --network network_b \
  nginx:latest

4.5.7 创建静态和动态测试文件

为了验证环境是否配置成功,可以创建简单的 HTML 和 PHP 文件:

# 创建静态 HTML 页面
vim ~/lnmp_b/www/index.html

内容如下:

hello lnmp_b

然后,创建 PHP 测试文件:

# 创建 PHP 测试文件
vim ~/lnmp_b/www/index.php

内容如下:

<?php
phpinfo();

4.5.8 验证数据库是否可用

进入 MySQL 容器,创建测试数据库,并查看是否成功:

# 连接数据库容器
docker exec -it mysql80_b mysql -uroot -proot_password

然后执行:

CREATE DATABASE IF NOT EXISTS docker_mysql80_db;
SHOW DATABASES;
exit;

还可以在主机上检查数据库文件是否创建成功:

ls ~/lnmp_b/mysql/

五、Docker Compose

采用上述方法,的确能够创建多个相互独立、互不干扰的容器,以此搭建不同项目,使其使用不同的运行环境。然而,该方法存在显著弊端,命令执行过程繁杂,所需配置众多,这不仅给后期维护带来极大困难,在进行环境迁移时也极为不便。

面对这类情况,通常会采用另一种解决方案——docker compose。它能有效简化容器的管理与部署流程,极大提升工作效率。

5.1 安装Docker Compose

依照文档中的指定命令逐步进行安装操作。安装完毕后,可通过查看版本号信息来确认安装是否成功。若能获取正确的版本信息,即表明安装过程顺利完成。

# 安装编译 Python 包所需的基础工具和 bcrypt 的依赖:
sudo yum install -y gcc openssl-devel bzip2-devel libffi-devel python3-devel make

# 升级 pip 和 setuptools
sudo pip3 install --upgrade pip setuptools wheel

# 安装 docker-compose
sudo pip3 install docker-compose

# 查看版本
docker-compose --version

安装Docker Compose过程

5.2 建立目录及核心配置文件

# 建立 lnmp_c 项目的各功能目录
mkdir -p ~/lnmp_c/{www,nginx,mysql}

# 建立 docker-compose.yml 文件
vim ~/lnmp_c/docker-compose.yml

5.3 编写docker-compose.yml

docker-compose.yml是整个配置体系中的核心文件。借助该文件,可将多个存在关联关系的容器统一定义在一处,从而避免手动输入冗长且复杂的命令。它能有效确保开发、测试以及生产环境的一致性,自动处理容器之间的依赖关系,实现整个应用的快速启动与销毁,极大地提升了项目部署与管理的便捷性。

version: "3"

services:
  nginx:
    image: nginx
    container_name: nginx_c
    restart: always
    ports:
      - 8083:80
      - 4433:443
    volumes:
      - ~/lnmp_c/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ~/lnmp_c/www:/var/www/html

  php:
    image: php:7.4-fpm
    container_name: php74_c
    restart: always
    volumes:
      - ~/lnmp_c/www:/var/www/html

  mysql:
    image: mysql:8.0
    container_name: mysql80_c
    restart: always
    ports:
      - 33063:3306
    volumes:
      - ~/lnmp_c/mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root_password
      - MYSQL_DATABASE=lnmp_c
      - MYSQL_USER=lnmp_c_user
      - MYSQL_PASSWORD=lnmp_c_password

5.4 编写nginx conf配置

# nginx conf 配置文件
vim ~/lnmp_c/nginx/default.conf

########## 将下方内容复制至配置文件内 ##########
server {
    listen 80;
    server_name localhost;
    root /var/www/html;

    location / {
        index index.php index.html;
    }

    location ~ \.php$ {
        fastcgi_pass php74_c:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
########## 将上方内容复制至配置文件内 ##########

5.5 启动服务

依据预先编写好的docker-compose.yml配置文件,执行特定命令,即可自动创建相关容器,快速搭建起完整的运行环境。

# 进入目录
cd lnmp_c

# 启动容器
docker-compose up -d

# 建立网站静态文件
vim ~/lnmp_c/www/index.html

# 内容
hello lnmp_c

# 建立网站 php 文件
vim ~/lnmp_c/www/index.php

# 内容
<?php
phpinfo();

# 查看数据库文件
ls ~/lnmp_c/mysql/

5.6 建立静态及动态测试文件

创建静态的html文件与动态的PHP文件,以此检验已创建好的容器是否能够正常解析这两类文件,进而验证整个环境的功能性。

5.7 查看数据库文件

由于在配置文件中已预先创建了一个数据库,通过相关命令在文件系统中进行查看,能够确切地找到对应的数据库文件,这进一步证明了数据库的创建操作准确无误。

5.8 docker-compose.yml文件介绍

此部分主要对配置文件中的三个核心组成部分进行详细说明。在阅读和编写该文件时,需重点关注类似于-v、-p、-e这类参数的设置,它们分别对应端口映射、文件映射以及环境变量的配置,这些参数的正确设置对于整个容器环境的正常运行至关重要。

5.9 docker-compose的启动与重启

通过docker compose方式创建的容器,在重启操作方面具备极高的便捷性。重启操作主要可分为相对路径重启和绝对路径重启两种方式。

方法一:相对路径写法

# 停止并删除所有由 Compose 管理的容器
docker-compose down

# 启动容器
docker-compose up -d

方法二:绝对路径写法

# 停止并删除所有由 Compose 管理的容器
docker-compose -f ~/lnmp_c/docker-compose.yml down

# 启动容器
docker-compose -f ~/lnmp_c/docker-compose.yml up -d

六、迁移测试

6.1 迁移说明

在服务器迁移场景中,操作极为简便。仅需将当前服务器上项目lnmp_c的目录完整复制到目标服务器。随后,在目标服务器上进入指定目录,重新执行docker-compose up -d命令,系统便能一键自动拉取并创建项目lnmp_c所需的全部容器。由于整个项目目录被一同打包迁移,网站文件与数据库数据得以完整保留,确保迁移后项目的正常运行不受影响。

6.2 迁移前数据库准备

为全面且精准地测试数据迁移的完整性,在迁移操作前,需通过终端对项目c的数据库进行如下准备工作:创建特定的表,并添加一些数据记录。后续可通过对比迁移前后的数据,来验证迁移效果。

docker exec -it mysql80_c mysql -uroot -proot_password

SHOW DATABASES;

use lnmp_c;

CREATE TABLE `test` (
  `id` int(11) NOT NULL,
  `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `test` (`id`, `title`) VALUES
(1, 'title'),
(2, 'test');

ALTER TABLE `test`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `test`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;

SELECT * FROM `test`;

exit;

6.3 迁移过程说明

本次迁移测试选用一台全新的测试服务器。通过执行相关命令,可清晰看到项目c的文件已成功复制至该服务器,且此时服务器上尚未安装任何相关镜像与容器。当执行启动docker compose文件的命令后,服务器即刻自动开始拉取项目所需的镜像,并依照配置自动创建对应的容器。

容器创建完成后,通过在浏览器中输入“IP地址加端口”的方式,能够顺利访问项目的静态页面与动态页面。同时,借助终端进入数据库容器,经检查发现,此前创建的数据库表以及添加的数据记录均完整无缺地保留了下来。由此可见,通过这种基于Docker compose的迁移方式,能够确保新旧服务器在程序运行、数据库状态以及整体环境等方面完全一致,有力保障了项目迁移的高效性与稳定性。

迁移过程演示

总结

本期教程至此已全部结束。通过对Docker两种使用方法的对比分析,不难发现Docker compose在实际应用中展现出了更高的灵活性与便捷性。因此,在日常工作及项目部署中,强烈推荐使用Docker compose的方式来构建和管理Docker容器环境,以提升工作效率,优化项目部署流程。

原文阅读

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件举报,一经查实,本站将立刻删除。

文章由技术书栈整理,本文链接:https://study.disign.me/article/202511/14.docker-and-docker-compose-application-deployment.md

发布时间: 2025-03-13