又是新学期,为了便于工作室招新决定临时搭建招新网站,本来是想手撸的,但是8月上旬开发组都有私事给耽搁了,下旬又有其他事情,遂决定基于wordpress搭建个网站先用着,折腾了两天,也接触了许多之前不知道的知识,特此记录(每水一篇博客都能带来极大的满足)....
初遇 Docker
上一篇博客提过,21年暑假搭建个人博客时,由于对linux不熟悉,所以就使用宝塔面板一键安装LNMP环境,有一说一,确实好用,对于小白特别友好。
但一方面师兄说宝塔风评不好(虽然也没指出到底哪不好),另一方面想着作为科班学生,还是要乐于学习新事物(对我来说),乐于折腾新东西的,于是就尝试采用docker部署
Windows下使用Docker
为了便于更好的探索docker,所以想在本机上用一用(电脑性能不好,虚拟机总是感觉卡卡的,也不愿重装linux系统
windows还要用来打游戏呢,更没钱重新买一台linux的电脑vps也买不起,暑假没生活费好惨)...
指导教程,下面记录一下我遇到的关键问题,以及大概流程
- windows系统需升级到专业版(一般来说都是家庭版的,升级之后需要重新激活....)
- 开启Hyper-v服务(前提是升级到windows专业版)
- 这里遇到一个困扰我近半个小时的问题:开启该服务重启电脑总是在最后提示无法实现相关功能,正在撤销更新
- 解决办法:修复windows10(过程大概需要2~3小时)
- 安装wsl2
- 安装过程
- 验证是否安装成功:
- 安装Docker Desktop
- 前面都可行的话,这一步我没有遇到问题:
Docker知识补充
docker的出现解决了软件开发部署过程中的环境一致性问题(docker的应用场景应该不止这些,但是笔者目前接触有限,仅从这方面谈一谈...)
为什么使用Docker ?
软件的运行环境一般有两方面: - 操作系统内核(Kernel)提供 - 各种运行库(Runtime Library)提供 - 关于运行库,不同于前端开发时的各种第三方依赖包(比如:npm包,通过package-lock.json就能很好的统一管理),而是指nodejs等软件中脚本的运行时...
下面举几个例子进而说明docker的作用:
- 软件开发时的系统是Ubuntu,但是生产环境的系统是CentOS,那么部署就可能出问题?(比如某个在Ubuntu运行正常的数据库在CentOS上运行报错)...
- php开发的网站与java开发的网站依赖环境不同,将其部署于一个服务器上可能会造成冲突(比如两者使用的web server分别是IIS和Apache,那么就可能存在端口访问冲突)...
Docker是通过怎样的手段解决了上述问题呢??
Docker利用了linux的namespace隔离技术为基础,通过共享Linux内核实现的
插一句题外话:linux和windows系统既支持X86,也支持ARM(当然不同架构下内核代码肯定有区别),而X86和ARM是CPU设计的不同
操作系统该复习了...
无论是Ubuntu还是CentOS,都使用linux内核,区别仅在于添加了不同的工具软件(GUI,函数库,软件包管理工具(yum/apt-get)等...),Docker技术主要使用了两个内核模块:
因此在CentOS上运行基于Ubuntu镜像的容器时, 容器使用了CentOS主机的内核以及Ubuntu镜像, Ubuntu镜像中安装了Ubuntu的各种软件。
Docker 基本概念
Docker最重要的两个概念:镜像(Image)和容器(Container),其中Image是多层存储,每一层是在前一层的基础上进行的修改;而容器同样也是多层存储,是在以镜像为基础层,在其基础上加一层作为容器运行时的存储层。
以nginx为例: 1
2
3
4
5
6
7
8
9
10docker run --name NginxTest -d -p 80:80 nginx
本地访问localhost就可以看到Nginx默认的欢迎页面
docker exec -it NginxTest bash
进入NginxTest容器,并开启一个shell
echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
exit
退出容器再访问localhost发现内容被更改
docker diff
查看容器内文件哪些被修改
上述的更改均保存在容器运行时的存储层内(在内存中,不能持久化存储),因此如果直接结束容器运行,这些更改就会消失,想要将这些更改保存到镜像里,可以使用docker commit
命令(但是慎用,最好不要用...)
每当一个docker容器运行时,会生成一个sha-256值(前6位就是container ID),然后在宿主机的/var/lib/docker目录下的container文件夹下会生成一个与container ID相同名字的文件夹,此文件夹就是该容器运行的数据所在
可以看到熟悉的目录结构
下面讲讲数据卷?
(个人理解)一方面是实现数据的持久性存储(
便于其他容器共享和重用这一点由于使用经验较少还没感受到),另一方面就是便于运维人员操作容器内的文件,操作数据卷等价于操作容器内被挂载的文件(不需要进入容器内部更改数据文件了)
常见的是两种方式:
volumes由docker创建,非Docker应用程序不能改动这一位置的数据。 1
2
3
4
5
6
7
8
9
10docker volume create XXXX
创建一个名为XXXX的数据卷,存储在宿主机的/var/lib/docker/volumes目录下
将该数据卷挂载到某一容器的相应目录
docker run -d -P \
--name VolumeTest1 \
-v XXXX:/usr/share/nginx/index.html \
--mount source=XXX,target=/usr/share/nginx/index.html \
nginx1
2
3
4
5docker run -d -P \
--name VolumeTest2 \
-v /src/webapp:/usr/share/nginx/html \
--mount type=bind,source=/src/webapp,target=/usr/share/nginx/html \
nginx
自己尝试部署WordPress时,容器互联还在使用
--link
命令,师兄提醒我这已经过时了,于是就学习了通过docker的容器网络来连接多个容器....
Docker是通过Docker Network来实现容器之间互相访问的,它是一个虚拟网,可以通过bridge组建或overlay实现,通过docker network ls
可以查看宿主机当前运行的docker网络
如图所示,有三大网络模式,分别是bridge,host和none,除此之外还有一个自定义的网络wp,下面主要介绍一下bridge模式(默认模式)
在宿主机上执行ip address
可以看到docker0的网络,默认通过该网络实现宿主机与docker容器之间的网络通信,结构图如下:
进入nginx容器,查看hosts文件,可以看到该服务的内网IP,在宿主机上测试,可以通信
但是值得注意的是,宿主机的网络上一个名为br-66d0daa...
的网络,是我们自定义的bridge类型的网络,我们在宿主机上运行的docker服务会连接到该网桥上,看上图下面的几个veth对也可看出...
下面讲一下docker 容器之间的通信,从上面的结构图可知,容器之间可以通过docker0这个网桥进行通信,但是只能通过IP进行通信,不能通过服务名称进行通信,docker容器的IP是动态分配的,如果一个容器重新启动可能就会分配不同的ip,那么就很有可能出现问题...
如何解决这个问题呢?
相关网桥写文章之前已经搭建完毕,这里查看一下其信息:
1 | docker network inspect wp #wp为自定义网桥名称 |
进入wordpress容器测试能否ping通nginx:
部署WordPress
上面补充的docker知识已经足够完成搭建任务了,下面给出部署过程
- 拉取镜像
1 | docker pull wordpress |
- 创建自定义网桥
1
docker network create -d bridge wp
- 启动wordpress容器
1
2
3
4
5
6
7docker run --name wordpress \
--network wp \ #连接到自定义网桥
--mount source="$PWD/wordpress",target=/var/www/html \
-e WORDPRESS_DB_PASSWORD=XXXX \
-p 8080:80 \
-d \
wordpress - 启动mysql容器 至此访问
1
2
3
4
5
6
7
8docker run --name mysql \
--network wp \
--mount source="$PWD/mysql",target="/var/lib/mysql" \
-e MYSQL_DATABASE=wordpressDB \
-e MYSQL_ROOT_PASSWORD=XXXX \
-p 3306:3306 \
-d \
mysql[ip]:[port]
即可进入wordpress安装设置页...
补充一下:可能会有人困惑于建立数据卷及映射时容器内目录怎么来的(
没错是本人)?询问师兄后得到回复:去docker hub的相应镜像仓库下面看文档....
再遇 Nginx
学习半天docker,部署好之后,又被师兄发现一大堆问题,想要解决这些问题,就要使用另一个工具----nginx(之前为了解决跨域问题使用nginx做了反向代理,但还没有系统学习过...)
Nginx前置知识
上面提到在服务器部署项目时通常需要LNMP环境,也就是linux+nginx+mysql+php,有时是LAMP,也就是nginx->apache,这里的nginx和apache都是web server(也有区分,比如前者是web服务器,后者是应用服务器)
nginx是web服务器,我们平时在各大厂商购买的vps也是服务器,这两个服务器有什么区别呢?(下面说一下个人理解)
vps(Vitural private server)其实就是一台电脑(各厂商基于虚拟化技术虚拟出来的电脑),而nginx可以看作在这台电脑上运行的服务,帮助我们实现网络连接,路径寻找和会话管理等功能,所以nginx才是真正意义上为客户端提供服务的设备(当然其提供的资源存储在vps上...)
Nginx 配置
Nginx的配置是按照配置块来组织的,最外一层是mainn控制块,它是一个全局配置的区域,main配置块内有events(配置工作模式...)和http配置块,http内又有upstream(配置负载均衡)和server(配置虚拟主机...)配置块,server里面有location(URL匹配块...)等配置块...
下面主要讲一下http模块的配置:
Server配置快
server 配置块是用来配置虚拟主机的信息的,可以在这里配置虚拟主机监听的端口,域名,URL 重定向等。
1 | server { |
- listen:设置虚拟主机监听的端口
- server_name:设置虚拟主机的域名,中间使用空格隔开
- root:设置虚拟主机目录
- index:访问路径无指定文件时默认访问文件
- charset:指定特定的字符集到响应头部"Content-Type" 首部。
locatiion配置块
针对指定的URL进行配置
1
2
3
4
5
6 server {
location / {
root /var/www/;
index index.php index.html index.htm;
}
}
root和index的含义同server配置块,两者的区别在于location仅对其匹配的URL起效,server对所有URL起效。
Nginx 配置脚本
下面给出配置脚本并进行相关说明
1 | server { |