Docker - 搭建部署(Nginx+Mysql+Redis)应用服务和解决MacDocker0问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker - 搭建部署(Nginx+Mysql+Redis)应用服务和解决MacDocker0问题相关的知识,希望对你有一定的参考价值。

概述

使用docker搭建一个php、redis、mysqlnginx的常用实例,基础好的同学可直接跳过前面的基础讲解,直接开始实战,其中解决了Mac docker中实例间网络不通的问题,对docker宿主机的磁盘映射、网络通信有了更深层次的理解。

基础知识

在开始实践时,先看一下本地docker的部署架构图,独立的 php、redis、mysql、nginx各一台,一个lnmp一台,这是我们要实现的目的,容器间的互通,数据卷的映射。

镜像操作

1.查看docker版本

docker-compose --version
docker version

2.获取镜像

一般来说,镜像的latest标签意味着该镜像的内容会跟踪最新版本的变更而变化,内容是不稳定的。因此,从稳定性上考虑,不要在生产环境中忽略镜像的标签信息或使用默认的latest标记的镜像,镜像优先在本地查找如果没有就从dockerhub仓库里拉去。

docker pull php:7.4.25-fpm-buster

pull子命令支持的选项主要包括:

-a, --all-tags=true|false:是否获取仓库中的所有镜像,默认为否;
--disable-content-trust:取消镜像的内容校验,默认为真。

3.查看镜像

使用docker images命令可以列出本地主机上已有镜像的基本信息。

REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
mysql                          latest              b05128b000dd        5 days ago          516MB
php                            7.4.25-fpm-buster   918ac8229863        4 weeks ago         405MB
redis                          latest              7faaec683238        5 weeks ago         113MB
nginx                          latest              87a94228f133        6 weeks ago         133MB

TAG信息用于标记来自同一个仓库的不同镜像。例如ubuntu仓库中有多个镜像,通过TAG信息来区分发行版本,如18.04、18.10等。

另外,使用inspect命令查看详细信息。

docker docker image inspect 192.168.0.177:5000/gzcp:1.3

4.存入和导出镜像

导出镜像:

docker save -o ~/gzcp.tar 192.168.0.177:5000/gzcp:1.3

存入镜像:

docker load -i gzcp.tar

有不清楚的地方,可以执行帮助命令 docker image help

5.删除镜像和实例

这里有一个地方要注意,docker rmi 删除的是镜像,rmi 代表的是images的意思, docker rm 删除的是docker的实例

docker rmi 15117995393/gzcp_dev:gzcp_dev

容器操作

1.登陆容器

bash:以bash的形式进行交互模式

docker exec -it d1854ecb30df bash

2.删除容器

docker rm 

默认情况下,docker rm命令只能删除已经处于终止或退出状态的容器,并不能删除还处于运行状态的容器,强制删除参数加-f

3.容器的导出与导入

导出镜像命令

docker export -o ~/lnmp1.7.tar 804c161615c3

导入镜像命令

docker import ~/lnmp1.7.tar -t lnmp

4.查看容器

查看容器详情命令

docker inspect stark_lnmp:v1.0

查看容器内进程,b0b5a9371ce4是容器ID

docker top b0b5a9371ce4

查看docker状态

docker stats

Docker数据管理

1.数据卷

数据卷(Data Volumes)是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于Linux中的mount行为。

docker volume create -d local test test

2.绑定数据卷

除了使用volume子命令来管理数据卷外,还可以在创建容器时将主机本地的任意路径挂载到容器内作为数据卷,这种形式创建的数据卷称为绑定数据卷。

-mount选项支持三种类型的数据卷,包括:

  • -mount选项支持三种类型的数据卷,包括:
  • bind:绑定数据卷,映射到主机指定路径下;
  • tmpfs:临时数据卷,只存在于内存中。

下面使用training/webapp镜像创建一个Web容器,并创建一个数据卷挂载到容器的/opt/webapp目录:

docker run -d -P --name web --mount type=bind,source=/webapp, destination=/opt

上述命令等同于使用旧的-v标记可以在容器内创建一个数据卷:

docker run -d -P --name web 
-v /webapp:/opt/webapp 
training/webapp bash

另外,本地目录的路径必须是绝对路径,容器内路径可以为相对路径。如果目录不存在,Docker会自动创建。

3.数据卷容器

如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门提供数据卷给其他容器挂载。

创建一个数据卷容器dbdata,并在其中创建一个数据卷挂载到/dbdata:

docker run -it -v /dbdata --name dbdata alpine

然后,可以在其他容器中使用--volumes-from来挂载dbdata容器中的数据卷,例如创建db1和db2两个容器,并从dbdata容器挂载数据卷。

docker run -it --volumes-from dbdata --name db1 alpine

注意:使用--volumes-from参数所挂载数据卷的容器自身并不需要保持在运行状态。

端口映射与容器互联

1.从外部访问容器应用

在启动容器时加入映射端口 -p 宿主机端口:容器端口

docker run -it -d -p 6379:6379 redis bash 

2.互联机制实现便捷互访

使用--link参数可以让容器之间安全地进行交互。

docker run -it --link redis-test:74-fpm b6086f719fea bash

实战 单独安装部署Mysql、Redis、PHP、Nginx 应用

执行命令,查看本地镜像,stark_lnmp:v1.0 是我之前集成了lnmp1.7的镜像,有需要的同学可以从我要镜像地址

➜  Docker docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
stark_lnmp                     v1.0                279e576fa083        4 weeks ago         5.43GB

执行命令:

docker run -d -i -t --privileged=true --name lnmp
-p 90:80
-p 453:443
-p 6389:6379
-p 11221:11211
-p 3316:3306
-v /Users/stark/ChangPei/Docker/lnmp/wwwroot:/home/wwwroot 
stark_lnmp:v1.0 bash

登陆docker:

docker exec -it 21e94b048331 bash

启动lnmp

[root@7d63a5989e81 default]# lnmp
+-------------------------------------------+
|    Manager for LNMP, Written by Licess    |
+-------------------------------------------+
|              https://lnmp.org             |
+-------------------------------------------+
Usage: lnmp start|stop|reload|restart|kill|status
Usage: lnmp nginx|mysql|mariadb|php-fpm|pureftpd start|stop|reload|restart|kill|status
Usage: lnmp vhost add|list|del
Usage: lnmp database add|list|edit|del
Usage: lnmp ftp add|list|edit|del|show
Usage: lnmp ssl add
Usage: lnmp dnsssl|dns cx|ali|cf|dp|he|gd|aws
Usage: lnmp onlyssl cx|ali|cf|dp|he|gd|aws

mysql测试:

$link = mysqli_connect(127.0.0.1, root, 12345678,test);

$sql = "select `id`,`page_name` from `t_page`  limit 0,5";

$result = mysqli_query($link,$sql);

while ( $row=mysqli_fetch_array($result,MYSQLI_ASSOC) ) 
    echo "id:".$row[id].",page_name:".$row[page_name].PHP_EOL;

执行结果:

[root@7d63a5989e81 default]# php mysql.php
id:1,page_name:公司简介
id:2,page_name:企业荣誉
id:3,page_name:发展历程
id:4,page_name:联系我们
id:5,page_name:人才招聘

Mysql,

docker pull mysql:5.6

docker run -itd --name mysql1 -p 3326:3306 -e MYSQL_ROOT_PASSWORD=rootroot mysql:5.6

redis

docker pull redis:6.2.6

2.修改默认配置

bind 127.0.0.1 #注释掉这部分,这是限制redis只能本地访问

protected-mode no #默认yes,开启保护模式,限制为本地访问

daemonize no#默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败

databases 16 #数据库个数(可选),我修改了这个只是查看是否生效。。

dir  ./ #输入本地redis数据库存放文件夹(可选)

appendonly yes #redis持久化(可选)

3.启动redis

docker run -p 6399:6379 --name redis1 
-v /Users/stark/ChangPei/Docker/redis/redis1.conf:/etc/redis/redis.conf
-v /Users/stark/ChangPei/Docker/redis/data:/data 
-d redis:6.2.6 redis-server /etc/redis/redis.conf
--appendonly yes

php+Nginx

docker pull php:7.4-fpm

2.运行

docker run --name  phpfpm1 
-v /Users/stark/ChangPei/Docker/nginx/www:/www 
-d php:7.4-fpm

3.安装Nginx

docker run --name runoob-php-nginx -p 8083:80 -d \\
    -v /Users/stark/ChangPei/Docker/nginx/www:/usr/share/nginx/html:ro \\
    -v /Users/stark/ChangPei/Docker/nginx/conf/conf.d:/etc/nginx/conf.d:ro \\
    --link phpfpm1:php \\
    nginx:1.20

Mac Docker宿主机与容器不能通信问题

问题说明:再容器安装成功后,我遇到一个问题,好久不能得到解答,前几天终于茅塞顿开,为此我在放假期间,特意学了一遍Docker,从数据卷、网络方面入手,我当时所困惑的问题是为什么用客户端从外网可以访问,但是我容器中的PHP代码不能访问呢?

lnmp的docker实例中,php和mysql就可以正常访问到,但是到了容器间通信的时候就链接不到了,但是用客户端软件链接时却可以正确访问到。

访问代码:

$redis = new Redis();
try
    $redis->connect(172.17.0.4,6379 );
    echo "Connection to server successfully".PHP_EOL;
//查看服务是否运行
    echo "Server is running: " . $redis->ping().PHP_EOL;
catch ( Exception $e )
    echo $e->getMessage();

“Connection refused”报错信息,是因为没有开启服务端,或者网络不通。我想尽办法都还是不行。

后来知道了底层的网络原理,原因是这样的,Docker的通信默认是网桥,宿主机和容器不在同一个网桥里,Mac的网桥里少了Docker0网段,外部部署的网络之所以能通是因为访问服务时,网段进行了网络的Nat的自动转换,lnmp可以访问到是因为所有的服务都部署在了同一个容器中,原来是这样。

知道的原理确实是不一样的,之后我也遇见过类似的问题,便可轻松化解,下面我说一下这个问题的解决办法。

1. 使用 docker-connector,然后执行以下命令把 docker 的所有 bridge 网络都添加到路由中。

brew install wenjunxiao/brew/docker-connector
docker network ls --filter driver=bridge --format ".ID" | xargs docker network inspect --format "route range .IPAM.Config.Subnetend" >> /usr/local/etc/docker-connector.conf

也可以手动修改 /usr/local/etc/docker-connector.conf 文件中的路由,格式是:

route 172.17.0.0/16

配置完成,直接启动服务(需要 sudo,路由配置启动之后仍然可以修改,并且无需重启服务立即生效)

sudo brew services start docker-connector
docker run -it -d --restart always --net host --cap-add NET_ADMIN --name connector wenjunxiao/mac-docker-connector

查看容器,启动成功了,问题就解决了,访问时把容器Ip绑定在Dns上就可以了。

~ docker ps
7c25a002e978 wenjunxiao/mac-docker-connector   "mac-receiver"          

测试一下,Mysql、Redis都可以链接了!

$redis = new Redis();
try
    $redis->connect(172.17.0.4,6379 );
    echo "Connection to server successfully".PHP_EOL;
//查看服务是否运行
    echo "Server is running: " . $redis->ping().PHP_EOL;
catch ( Exception $e )
    echo $e->getMessage();

以上是关于Docker - 搭建部署(Nginx+Mysql+Redis)应用服务和解决MacDocker0问题的主要内容,如果未能解决你的问题,请参考以下文章

docker部署lnmp环境搭建php项目

Docker快速搭建PHP+Nginx+Mysql环境(https://notemi.cn/docker-quickly-set-up-php-nginx-mysql-environment.html

docker部署nacos集群并配置mysql8

docker部署django项目mysql主从搭建django实现读写分离

Zabbix- 使用docker部署

docker部署lnmp环境