开源web框架django知识总结(十四)
容器化方案Docker
- 涉及到相同的工作是否需要重复做。
- 避免相同的工作重复做是容器化技术应用之一。
1. Docker介绍
Docker通常用于如下场景:
-
web应用的自动化打包和发布;
-
自动化测试和持续集成、发布;
-
在服务型环境中部署和调整数据库或其他的后台应用;
-
Docker 是一个开源的软件部署解决方案。
-
Docker 也是轻量级的应用容器框架。
-
Docker 就像一个盒子,里面可以装很多物件,如果需要某些物件,可以直接将该盒子拿走,而不需要从该盒子中一件一件的取。
-
Docker 是一个"客户端-服务端(C/S)"架构程序。
- 客户端只需要向服务端发出请求,服务端处理完请求后会返回结果。
Docker 包括三个基本概念:
- 镜像(Image)
- Docker的镜像概念类似于虚拟机里的镜像,是一个只读的模板,一个独立的文件系统,包括运行容器所需的数据,可以用来创建新的容器。
- 例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了MySQL或用户需要的其它应用程序。
- 容器(Container)
- Docker容器是由Docker镜像创建的运行实例,类似VM虚拟机,支持启动,停止,删除等。
- 每个容器间是相互隔离的,容器中会运行特定的应用,包含特定应用的代码及所需的依赖文件。
-
仓库(Repository)
- Docker的仓库功能类似于Github,是用于托管镜像的。
2. Docker安装(ubuntu 18.04)
1,更新ubuntu的apt源索引
sudo apt-get update
2, 安装包允许apt通过HTTPS使用仓库,安装证书
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
如果出现上面报错,解决方法:
sudo rm /var/lib/dpkg/updates/*
sudo dpkg --configure -a
sudo apt-get update
sudo apt-get upgrade
注意:sudo apt-get upgrade中间会有个提示选择,选择“N”
解决方法:
sudo rm /var/cache/apt/archives/lock
sudo rm /var/lib/dpkg/lock
sudo rm /var/lib/dpkg/lock-frontend
再次执行:
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
添加docker的官方GPGkey(此步可能一次不能通过,多执行几次)
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
添加docker源
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
安装 docker ce
- 更新包索引
sudo apt-get update
2.安装docker
sudo apt-get install docker-ce
中间可能会卡在MySQL升级上:
Checking if update is needed.
This installation of MySQL is already upgraded to 5.7.33, use --force if you still need to run mysql_upgrade
使用另一个窗口,查看端口进程:
ps aux |grep mysql
kill -9 MySQL进程
3.启动docker
# 启动docker
sudo service docker start
# 停止docker
sudo service docker stop
# 重启docker
sudo service docker restart
4.检测是否安装成功
sudo docker run hello-world
安装成功会出现如下输出:
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
5.停止与启动容器
# 停止一个已经在运行的容器
docker stop 容器名或容器id
# 启动一个已经停止的容器
docker start 容器名或容器id
# kill掉一个已经在运行的容器
docker container kill 容器名或容器id
为了避免每次命令都输入sudo,可以设置用户权限,注意执行后须注销重新登录
sudo usermod -a -G docker pyvip
6..删除镜像 先停止,再删除
7、docker的run模式
交互模式:
(py3env) pyvip@VIP:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
(py3env) pyvip@VIP:~$ docker run -it --name=ubuntu ubuntu:16.04 /bin/bash
root@7e9e711ebe04:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@7e9e711ebe04:/# exit
exitpyvip@VIP:~$
守护进程:(需要先删除容器,再次创建)
(py3env) pyvip@VIP:~$ docker ps -a
\CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2869eefe3389 ubuntu:16.04 "/bin/bash" 32 seconds ago Exited (0) 8 seconds ago ubuntu
(py3env) pyvip@VIP:~$ docker run -dit --name=ubuntu ubuntu:16.04 /bin/bash
docker: Error response from daemon: Conflict. The container name "/ubuntu" is already in use by container "2869eefe3389caad41deeec097c927c27bf75d6e264865a27b6394d67ea2b093". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
(py3env) pyvip@VIP:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2869eefe3389 ubuntu:16.04 "/bin/bash" About a minute ago Exited (0) About a minute ago ubuntu
(py3env) pyvip@VIP:~$ docker rm 286
286
(py3env) pyvip@VIP:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
(py3env) pyvip@VIP:~$ docker run -dit --name=ubuntu ubuntu:16.04 /bin/bash
9e476b0f7ee11403d70c98ba185a90a045c7335f8c327563670927d8ebcaa142
(py3env) pyvip@VIP:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e476b0f7ee1 ubuntu:16.04 "/bin/bash" 6 seconds ago Up 5 seconds ubuntu
(py3env) pyvip@VIP:~$ docker exec -it ubuntu /bin/bash
root@9e476b0f7ee1:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@9e476b0f7ee1:/#
8、docker打包:(注意查询时:–all与-all查询可能不同,我们用–all)
(py3env) pyvip@VIP:~$ docker container ls --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5604475eb9a4 ubuntu:16.04 "/bin/bash" 3 minutes ago Up 2 minutes ubuntu
67b6e4a3724b ubuntu:16.04 "/bin/bash" 44 minutes ago Exited (127) 21 minutes ago wizardly_taussig
1b2b92078237 hello-world "/hello" 2 hours ago Exited (0) 2 hours ago romantic_thompson
ffc680e77469 delron/fastdfs "/usr/bin/start1.sh …" 7 hours ago Up 7 hours storage
772eb3b9c15c delron/fastdfs "/usr/bin/start1.sh …" 7 hours ago Up 7 hours tracker
(py3env) pyvip@VIP:~$ docker commit ubuntu ubuntu_tmp
sha256:85fcf0403c53baa1fa83dfc87c2f398c0bab4919b9813f7f2e7af4ed81572971
(py3env) pyvip@VIP:~$ docker save -o ubuntu16.04.rar ubuntu_tmp
(py3env) pyvip@VIP:~$ ls
af_pro fastdfs_docker.tar mysql_slave python_case 模板 下载
config fdfs_client-py-master.zip nginx.conf snap 使用方法.txt 音乐
data.tar.gz install.sh node-v10.15.3 sources.list 视频 桌面
elasticsearch-2.4.6 master_db.sql node-v10.15.3.tar.gz ubuntu16.04.rar 图片
elasticsearch-ik-2.4.6_docker.tar 'mysql_docker_5722 2.tar' projects 公共的 文档
(py3env) pyvip@VIP:~$
Docker 命令大全一键跳转
准备商品数据
提示:
- 数据库表有了以后,我们现在需要准备商品信息数据和商品图片数据,以便查询和展示。
- 商品信息数据:比如商品编号等都是字符串类型的,可以直接存储在MySQL数据库。
- 商品图片数据:MySQL通常存储的是图片的地址字符串信息。
- 所以图片数据需要进行其他的物理存储。
图片物理存储思考:
- 需要提供图片上传和下载的机制。
- 需要解决图片备份和扩容的问题。
- 需要解决图片重名的问题等等。
图片物理存储方案:
- FastDFS
=================================
文件存储方案FastDFS
1. FastDFS介绍
-
用
c语言
编写的一款开源的轻量级分布式文件系统。 -
功能包括:文件存储、文件访问(文件上传、文件下载)、文件同步等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。
-
为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标。
-
可以帮助我们搭建一套高性能的文件服务器集群,并提供文件上传、下载等服务。
-
FastDFS架构包括
Client
、Tracker server
和Storage server
。 -
Client
请求Tracker
进行文件上传、下载,Tracker
再调度Storage
完成文件上传和下载。 -
Client: 客户端,业务请求的发起方,通过专有接口,使用TCP/IP协议与
Tracker
或Storage
进行数据交互。FastDFS提供了upload
、download
、delete
等接口供客户端使用。 -
Tracker server:跟踪服务器,主要做调度工作,起负载均衡的作用。在内存中记录集群中所有存储组和存储服务器的状态信息,是客户端和数据服务器交互的枢纽。
-
Storage server
:存储服务器(存储节点或数据服务器),文件和文件属性都保存到存储服务器上。Storage server直接利用OS的文件系统调用管理文件。
- Storage群中的横向可以扩容,纵向可以备份。
2. FastDFS上传和下载流程
3. FastDFS文件索引
-
FastDFS上传和下载流程可以看出都涉及到一个数据叫文件索引(file_id)
- **文件索引(file_id)**是客户端上传文件后Storage返回给客户端的一个字符串,是以后访问该文件的索引信息。
- 文件索引(file_id)信息包括:组名、虚拟磁盘路径、数据两级目录、文件名等信息。
- 组名:文件上传后所在的 Storage 组名称。
-
虚拟磁盘路径:Storage 配置的虚拟路径,与磁盘选项
store_path*
对应。如果配置了store_path0
则是M00
,如果配置了store_path1
则是M01
,以此类推。 - 数据两级目录:Storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。
-
文件名:由存储服务器根据特定信息生成,文件名包含:源存储服务器IP地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。
4. Docker安装运行FastDFS(本地)
1.获取FastDFS镜像
docker load -i fastdfs_docker.tar
2.开启tracker容器
- 我们将 tracker 运行目录映射到宿主机的
/var/fdfs/tracker
目录中。
# 安装tracker
docker run -dti --network=host --name tracker -v /var/fdfs/tracker:/var/fdfs delron/fastdfs tracker
3.开启storage容器
- TRACKER_SERVER=Tracker的ip地址:22122(Tracker的ip地址不要使用127.0.0.1)
- 我们将 storage 运行目录映射到宿主机的
/var/fdfs/storage
目录中。 - 查看虚拟机ip 命令:ifconfig(如果报错,安装:sudo apt-get install net-tools)
# 10.0.2.15 虚拟机安装(vbox)
# 安装storage, IP地址用虚拟机的, 如果是云服务器就用云服务器的IP -e 为容器设置一个环境变量
docker run -dti --network=host --name storage -e TRACKER_SERVER=10.0.2.15:22122 -v /var/fdfs/storage:/var/fdfs delron/fastdfs storage
# 虚拟机安装(VM)
docker run -dti --network=host --name storage -e TRACKER_SERVER=192.168.42.128:22122 -v /var/fdfs/storage:/var/fdfs delron/fastdfs storage
# 云服务器的安装
docker run -dti --network=host --name storage -e TRACKER_SERVER=123.57.76.69:22122 -v /var/fdfs/storage:/var/fdfs delron/fastdfs storage
注意:如果无法重启storage容器,可以删除/var/fdfs/storage/data目录下的fdfs_storaged.pid 文件,然后重新开启storage。
sudo rm /var/fdfs/storage/data/fdfs_storaged.pid
docker run -dti --network=host --name storage -e TRACKER_SERVER=192.168.235.129:22122 -v /var/fdfs/storage:/var/fdfs delron/fastdfs storage
4.查看宿主机映射路径
5. FastDFS客户端上传文件
1.安装FastDFS客户端扩展
安装准备好的fdfs_client-py-master.zip
到虚拟环境中
#注意,要在.zip压缩文件所在的文件内执行
pip install fdfs_client-py-master.zip
pip install mutagen==1.44.0 #注意,当前最新版本 有些东西变了,不指定,运行会报错
pip install requests
注意:别忘了在执行前,切换到项目的虚拟环境中。
2.准备FastDFS客户端扩展的配置文件
- 新建包.fastdfs
- 新建aerf_mall.utils.fastdfs.client.conf`
# connect timeout in seconds
# default value is 30s
connect_timeout=30
# network timeout in seconds
# default value is 30s
network_timeout=60
# the base path to store log files 玩云的同学需要注意下这里的路径
base_path=/Home/pyvip/test99/logs/fast.log
# tracker_server can ocur more than once, and tracker_server format is
# "host:port", host can be hostname or ip address 同学需要注意下这里的ip
tracker_server=192.168.42.128:22122
#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### error
### warn for warning
### notice
### info
### debug
log_level=info
# if use connection pool
# default value is false
use_connection_pool = false
# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
connection_pool_max_idle_time = 3600
# if load FastDFS parameters from tracker server
# default value is false
load_fdfs_parameters_from_tracker=false
# if use storage ID instead of IP address
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# default value is false
use_storage_id = false
# specify storage ids filename, can use relative or absolute path
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
storage_ids_filename = storage_ids.conf
#HTTP settings
http.tracker_server_port=80
3.准备FastDFS客户端扩展的fastdfs_storage.py文件
from django.core.files.storage import Storage
from django.conf import settings
from fdfs_client.client import Fdfs_client
class FastDFSStorage(Storage):
'''fafs dfs 文件存储类'''
def __init__(self,client_conf=None,base_url=None):
if client_conf is None:
client_conf = settings.FDFS_CLIENT_CONF
self.client_conf = client_conf
if base_url is None:
base_url = settings.FDFS_URL
self.base_url = base_url
def _open(self,name,mode='rb'):
'''打开文件'''
pass
def _save(self,name,content):
'''保存文件'''
# name:选择上传文件的名字,content:上传文件内容的File对象
# 创建一个Fdfs_client对象
client = Fdfs_client(self.client_conf)
# 上传文件到fast dfs系统中
res = client.upload_by_buffer(content.read())
# res 返回值
# dict
# {
# 'Group name': group_name,
# 'Remote file_id': remote_file_id,
# 'Status': 'Upload successed.',
# 'Local file name': '',
# 'Uploaded size': upload_size,
# 'Storage IP': storage_ip
# }
if res.get('Status') != 'Upload successed.':
raise Exception('上传失败')
# 返回上传文件的ID
filename = res.get('Remote file_id')
# print(filename)
# return self.tracker_server + filename.replace('\\', '/')
return filename
def exists(self, name):
# 判断文件名是否可用
return False
def url(self, name):
# 返回访问文件的url路径
return self.base_url + name
4.FastDFS客户端实现文件存储
# 使用 shell 进入 Python交互环境
python manage.py shell
>>> from fdfs_client.client import Fdfs_client
>>> FDFS_Client = Fdfs_client('aerf_mall/utils/fastdfs/client.conf')
>>> ret = FDFS_Client.upload_by_filename('aerf_mall/static/frontend/images/adv01.jpg')
注意:演示错误地址,观察报错。
5.dev.py里面配置 地址
#分布式文件系统配置
FDFS_URL = 'http://192.168.42.128:8888/'
FDFS_CLIENT_CONF = os.path.join(BASE_DIR,'utils/fastdfs/client.conf')
DEFAULT_FILE_STORAGE = 'utils.fastdfs.fdfs_storage.FastDFSStorage'
在跨域设置中,新增:
CORS_ORIGIN_WHITELIST = [
'http://192.168.42.128',
'http://192.168.42.128:8888',
]
3. 浏览器下载并渲染图片
思考:如何才能找到在Storage中存储的图片?
-
协议
:http`
-
IP地址:127.0.0.1
-
Nginx
服务器的IP地址。 - 因为 FastDFS 擅长存储静态文件,但是不擅长提供静态文件的下载服务,所以我们一般会将 Nginx 服务器绑定到 Storage ,提升下载性能。
-
-
端口:8888
-
Nginx
服务器的端口。
-
-
路径:group1/M00/00/00/wKhnnlxw_gmAcoWmAAEXU5wmjPs35.jpeg
- 文件在Storage上的文件索引。
-
完整图片下载地址
-
http://127.0.0.1:8888/group1/M00/00/00/CgACD2AdBfOAFg-pAACbl1lbG3U010.jpg
-
4. FastDFS服务器录入图片数据
1.准备新的图片数据压缩包
2.删除 Storage 中旧的data目录
3.拷贝新的图片数据压缩包到 Storage,并解压
# 解压命令
sudo cp ~/data.tar.gz data.tar.gz
sudo tar -zxvf data.tar.gz
修改静态页面index.html内的ip地址:将http://127.0.0.1:8000改成http://192.168.42.128:8888