前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Docker - 搭建部署(Nginx+Mysql+Redis)应用服务和解决MacDocker0问题

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

原创
作者头像
stark张宇
修改2023-02-16 12:43:40
1.1K0
修改2023-02-16 12:43:40
举报
文章被收录于专栏:stark张宇

概述

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

基础知识

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

docker本地部署架构图
docker本地部署架构图

镜像操作

1.查看docker版本

代码语言:txt
复制
docker-compose --version
docker version

2.获取镜像

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

代码语言:txt
复制
docker pull php:7.4.25-fpm-buster

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

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

3.查看镜像

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

代码语言:txt
复制
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命令查看详细信息。

代码语言:txt
复制
docker docker image inspect 192.168.0.177:5000/gzcp:1.3

4.存入和导出镜像

导出镜像:

代码语言:txt
复制
docker save -o ~/gzcp.tar 192.168.0.177:5000/gzcp:1.3

存入镜像:

代码语言:txt
复制
docker load -i gzcp.tar

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

5.删除镜像和实例

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

代码语言:txt
复制
docker rmi 15117995393/gzcp_dev:gzcp_dev

容器操作

1.登陆容器

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

代码语言:txt
复制
docker exec -it d1854ecb30df bash

2.删除容器

代码语言:txt
复制
docker rm 

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

3.容器的导出与导入

导出镜像命令

代码语言:txt
复制
docker export -o ~/lnmp1.7.tar 804c161615c3

导入镜像命令

代码语言:txt
复制
docker import ~/lnmp1.7.tar -t lnmp

4.查看容器

查看容器详情命令

代码语言:txt
复制
docker inspect stark_lnmp:v1.0

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

代码语言:txt
复制
docker top b0b5a9371ce4

查看docker状态

代码语言:txt
复制
docker stats

Docker数据管理

1.数据卷

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

代码语言:txt
复制
docker volume create -d local test test

2.绑定数据卷

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

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

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

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

代码语言:txt
复制
docker run -d -P --name web --mount type=bind,source=/webapp, destination=/opt

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

代码语言:txt
复制
docker run -d -P --name web 
-v /webapp:/opt/webapp 
training/webapp bash

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

3.数据卷容器

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

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

代码语言:txt
复制
docker run -it -v /dbdata --name dbdata alpine

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

代码语言:txt
复制
docker run -it --volumes-from dbdata --name db1 alpine

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

端口映射与容器互联

1.从外部访问容器应用

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

代码语言:txt
复制
docker run -it -d -p 6379:6379 redis bash 

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

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

代码语言:txt
复制
docker run -it --link redis-test:74-fpm b6086f719fea bash

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

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

代码语言:txt
复制
➜  Docker docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
stark_lnmp                     v1.0                279e576fa083        4 weeks ago         5.43GB

执行命令:

代码语言:txt
复制
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:

代码语言:txt
复制
docker exec -it 21e94b048331 bash

启动lnmp

代码语言:txt
复制
[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测试:

代码语言:txt
复制
$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;
}

执行结果:

代码语言:txt
复制
[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,
代码语言:txt
复制
docker pull mysql:5.6

docker run -itd --name mysql1 -p 3326:3306 -e MYSQL_ROOT_PASSWORD=rootroot mysql:5.6
redis
代码语言:txt
复制
docker pull redis:6.2.6

2.修改默认配置

代码语言:txt
复制
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

代码语言:txt
复制
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
代码语言:txt
复制
docker pull php:7.4-fpm

2.运行

代码语言:txt
复制
docker run --name  phpfpm1 
-v /Users/stark/ChangPei/Docker/nginx/www:/www 
-d php:7.4-fpm

3.安装Nginx

代码语言:txt
复制
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就可以正常访问到,但是到了容器间通信的时候就链接不到了,但是用客户端软件链接时却可以正确访问到。

访问代码:

代码语言:txt
复制
$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 网络都添加到路由中。

代码语言:txt
复制
brew install wenjunxiao/brew/docker-connector
代码语言:txt
复制
docker network ls --filter driver=bridge --format "{{.ID}}" | xargs docker network inspect --format "route {{range .IPAM.Config}}{{.Subnet}}{{end}}" >> /usr/local/etc/docker-connector.conf

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

代码语言:txt
复制
route 172.17.0.0/16

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

代码语言:txt
复制
sudo brew services start docker-connector
代码语言:txt
复制
docker run -it -d --restart always --net host --cap-add NET_ADMIN --name connector wenjunxiao/mac-docker-connector

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

代码语言:txt
复制
~ docker ps
7c25a002e978 wenjunxiao/mac-docker-connector   "mac-receiver"          

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

代码语言:txt
复制
$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();
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 基础知识
    • 镜像操作
      • 容器操作
        • Docker数据管理
          • 端口映射与容器互联
            • Mysql,
            • redis
            • php+Nginx
        • 实战 单独安装部署Mysql、Redis、PHP、Nginx 应用
        • Mac Docker宿主机与容器不能通信问题
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档