Docker认知
1:安装docker
2:docker优势
- 统一环境,标准化部署
- 解决复杂的依赖问题:比如两个微服务的依赖相互冲突
- 隔离应用的运行环境:比如redis获取服务器的权限的漏洞
- 轻量级的虚拟环境,相比虚拟机而言开销速度快
- 统一的服务管理:不同的服务有不同的管理工具和方式,例如不同的语言,不同的版本
- dockerhub上有许多高价值的镜像可以直接使用
3:镜像和容器的介绍
- 镜像:相当于光盘,光盘里面存储的数据是只读的,不会被更改;可以吧镜像看做一个模板,蓝图
- 容器:容器是用镜像生成的docker实例,一个镜像可以生成多个容器,每个容器之间,容器与宿主之间都是相互隔离的;可以在功能上吧容器看做虚拟机
容器可以快速方便的运行,也可以方便的删除
4:手动启动容器
docker run -d -t -p 8000:5000 --name demo ubuntu:18.04
- run: 表示启动一个新的docker容器
- -d 容器在后台运行
- -t 极少会用到,表示让一个空白的ununtu镜像在后台运行
- -p 指定端口,表示本机访问的8000会被自动转到容器中的5000端口;前提是本机的8000端口没被占用
- ubuntu:18.04 是启动容器使用的镜像
- 每个容器生成后都有ID,并且每个容器的ID都是不一样的
5:启动容器的常见问题
端口占用
- 占用3456端口: docker run -t -d -p 3456:5000 --name test ununtu:18.04
- 运行一个使用3456端口的容器,会发现因为端口被占用而失败:docker run -t -d -p 3456:5000 --name test1 ununtu:18.04
- 删除test容器来关闭对3456端口的占用 docker rm -f test
- 再次运行容器发现任然失败,因为名字已经存在,test1容器虽然因为端口被占用而运行失败,但实际上容器已经生成了
- 这时候要么改名字要么删除容器重来
docker run -t -d -p 3456:5000 --name test2
docker rm -f test1
docker run -t -d -p 3456:5000 --name test1
6:在容器中安装必备的软件
假如我们要运行一个 flask web程序;用 exec 参数在运行中的Docker 容器里面执行命令安装必要的依赖库
- docker exec demo apt update
- docker exec demo apt -y install python3 python3-pip
- docker exec demo pip3 install flask
7:在demo容器中运行web程序
- 当前目录下有个a.py文件
- docker exec demo mkdir /code
- docker cp a.py "demo:/code/a.py"
- docker exec demo python3 /code/a.py
- flask默认的启动端口是5000,之前我们已经做了8000::5000的端口转发
8:用脚本的方式配置容器
之前的一系列命令有些繁琐;更好的方式是在宿主机写脚本,然后cp 到容器中直接运行
- 再用脚本方式运行程序之前,我们先清理刚才运行的程序
- Ctrl c终止进程:只是到后台运行
- docker stop 真正停止容器
写一个install.sh脚本用于安装软件:
# install.sh
apt update
apt -y install python3 python-pip
pip3 install flask
写一个run.sh脚本运行程序:
# run.sh
cd /code
cd /code
python3 a.py
9:运行脚本配置并开启新容器
我们可以先删除容器重新开始,也可以开一个新容器 demo1
- docker run -t -d -p 7000:5000 --name demo1 ubuntu:18.04
- docker exec demo1 mkdir /code
- docker cp install.sh "demo1:/code/install.sh"
- docker cp a.py "demo1:/code/a.py"
- docker exec demo1 bash /code/install.sh
- docker exec demo1 bash /code/run.sh
- localhost:7000
10:容器的其他操作
- 启动一个停止运行的容器:docker start demo
- 查看正在运行的容器:docker ps
- 停止容器:docker stop demo
- 再查看正在运行的容器,已经看不到demo了:docker ps
- 查看所有的容器,包括未运行的:docker ps -a
- 删除被停止的容器:docker rm demo
- 删除运行的容器:docker rm -f demo1
11:Dockerfile介绍
使用Dockerfile打包一个镜像并运行;优势解决手动执行命令;脚本的劣势,如果要启动多个容器,自制脚本每次都要重新安装配置一次
# 在Dockerfile 文件中#是注释
# FROM 用于指定构建镜像使用的基础镜像
FROM ununtu:18.04
# RUN 用于在构建镜像的时候在镜像中执行命令
RUN apt update
RUN apt -y install python3 python3-pip
RUN pip3 install flask
# COPY 相当于命令的 docker cp
# 把本机当前的目录下的app.py 文件拷贝到镜像中
# 不同的是可以自动创建不存在的目录
# WORKDIR 用于指定从镜像启动的容器内的工作目录
WORKDIR /code
# CMD 用于指定容器运行后要执行的命令和参数列表
CMD ["python3", "app.py"]
# ENTRYPOINT 参数用于指定容器运行后的入口程序,但是现在的这个参数意义已经很小了
12:使用Dockerfile构建镜像
本文件夹下有2个文件app.py和Dockerfile
- docker build -t webimage .
命令中参数 -t webimage 指定了镜像的名字为webimage,这个名字可以用于在之后从镜像启动容器,最后的. 用于指定构建镜像时候的工作目录为本机当前目录
- docker image 用于查看本机的镜像,包括下载的和构建的
- docker run -p 8001:5000 --name demo2 webimage
13:服务器安装Docker
把安装的脚本和程序文件都放在本机的app 目录下,一共有如下3个文件: install-docker.sh=> 在ubuntu服务器安装docker的脚本;Dockerfile,上面的Dockerfile;app.py 上面的web程序; 我们可以用scp命令把app目录拷贝到服务器中,windows用户必须用cmder软件才有scp 这个命令;或者用 其他上传程序也可以,下面的用户名和IP换成你购买的服务器的用户名和IP
- 拷贝:scp -r app your-ununtu@your-ip:/tmp
- 登录:ssh your-ubuntu@your-ip
- 安装docker:sh /tmp/app/install-docker.sh
- 打包(提权):sudo docker build -t webimage .
- 运行:sudo run -d -p 8000:5000 --name serverdemo webimage
14:数据卷介绍
我们可以在概念上把docker看做虚拟机,当容器被删除的时候,容器里的所有数据都会被删除,两个不同的容器之间无法互通,所有推出了数据卷 volume 功能
可以把数据卷理解为虚拟机的虚拟磁盘,独立于容器的文件,在容器中它被挂载为一个目录的形式,对于容器的应用来说,数据卷是透明的,无法感知它的存在,就是一个普通的文件夹,独立于容器存在,因此删除容器的时候数据卷不会受到影响
- 优点:多容器可以通过挂载同一个数据卷来共享数据,数据卷可以方便地备份,存储数据
15:数据卷的使用
- 创建一个volume:docker volume create testvolume
- 列出所有数据卷:docker volume ls
- 删除一个数据卷:docker volume rm testvolume
- 查看一下:docker volume ls
- 先创建一个volume:docker volume create web
- 在运行容器的时候,使用参数 --mount:docker run -d --name demovolume --mount source=web,target=/volume webimage
- --mount source=web,target=/volume,
就是把数据卷挂载到容器的 /volume上
16:数据卷的特性演示
没有保存在数据卷上的文件会在容器被删除后丢失
- 执行命令在容器的 /b.txt 写入时间内容并查看
docker exec demovolume sh -c 'date > /b.txt'
docker exec demovolume sh -c 'cat /b.txt'
- 删除容器后重新启动同名容器再查看,之前容器的内容已经没有了
docker rm -f demovolume
docker run -d --name demovolume --mount source=web,target=/volume webimage
docker exec demovolume sh -c 'cat /b.txt'
- 保存在数据卷上的内容即使容器被删除了仍然存在
docker exec demovolume sh -c 'date > /volume/b.txt'
docker rm -f demovolume
docker run -d --name demovolume --mount source=web,target=/volume webimage
docker exec demovolume sh -c 'cat /volume/b.txt'
- 多容器之间可以通过数据卷共享文件
docker run -d --name demovolume2 --mount source=web,target=/v2 webimage
docker exec demovolume2 sh -c 'cat /v2/b.txt'
17:共享目录
除了挂载数据卷外,docker 还可以挂载共享目录(这一点和虚拟机一样);优势:使用方便,易于理解
下面会从nginx 镜像运行一个nginx1的容器。并且设置了8080:80的端口映射;--mount参数的 type=bind 表明要挂载共享目录
把宿主机的当前目录映射为容器的 /usr/share/nginx/html;这样在宿主机中访问 localhost:8080 会自动访问宿主机当前目录下的 index.html 文件
- docker run -p 8080:80 --name nginx1 --mount type=bind,source="${PWD}",target=/usr/share/nginx/html/ nginx
需要注意的是 source 参数必须使用绝对路径,所以这里使用 “${PWD}”
的方式来在 Mac/Linux/Windows 中获取当前目录路径;这是一个可以在多平台通用的获取当前目录路径的方法(win下必须使用PowerShell),加引号是因为路径中可能含有空格等特殊符号,如果路径有空格而未加引号,会产生错误
18其他挂载模式
- 单文件挂载,单文件挂载一定要保证宿主机文件存在,否则这个路径会被认为是一个目录挂载
docker run -p 8081:80 --name nginx2 --mount type=bind,source="${PWD}/index.html",target=/usr/share/nginx/html/test.html nginx
这时候我们访问 http://localhost:8081 返回的是 nginx 的默认首页,而访问 http://localhost:8081/test.html
- 多文件挂载
docker run -p 80812:80 --name nginx3 --mount type=bind,source="${PWD}/index.html",target=/usr/share/nginx/html/test.html
--mount type=bind,source="${PWD}/test.html",target=/usr/share/nginx/html/test2.html
nginx
19:compose的介绍
解决多容器互相配合,协同工作;虽然可以手动配置多容器之间的虚拟网络,文件互访等功能来实现容器互相访问,但docker官方推出了composer 程序用于配置,管理多容器的运行;Compose通过单独的docker-compose.yml配置文件来管理一组容器
20:安装Compose
在Docker for mac,Docker for Windows中 docker-compose 是自带的;只有在linux服务器上,才需要单独安装
- 查看如下链接获取最新的版本:https://github.com/docker/compose/releases
- linux服务器安装方法:
sudo su
curl -L
https://github.com/docker/compose/releases/download/版本号/docker-compose
chmod +x /usr/local/bin/docker-compose
使用国内的地址来安装
sudo su
curl -L https://get.daocloud.io/docker/compose/releases/download/版本号/docker-compose
chmod +x /usr/local/bin/docker-compose
官方安装指南:
https://doc.docker.com/compose/install/
21:compose使用
compose 把一组容器作为一个项目来进行管理,并且会设置好容器之间的内部网络,每个容器在compose中被称为服务;composer使用docker-compose.yml文件来描述compose项目的构建;如同docker使用dockerfile来描述一个镜像的构建一样;
- 命令启动:docker-compose up(Ctrl c 终止项目的运行)
- 后台运行:docker-compose up -d
- 暂停运行:docker-compose stop
- 关闭并删除所有容器:docker-compose down
22:加速换源安装
- Docker镜像源可替换为中科大镜像源:https://lug.ustc.edu.cn/wiki/mirrors/help/docker
- 镜像地址如下:https://docker.mirrors.ustc.edu.cn/
- 在Linux服务器上换了后要用如下命令重启docker才能生效:service restart docker
23:可选的镜像
基于Alpine linux的alpine镜像,alpine已经是官方推荐的打包基础镜像
- 使用专有镜像,而不是在Ubuntu镜像上安装软件
- 使用基于alpine打包的镜像
24:镜像的分层构建和缓存
docker会对dockerfile中执行的结果生成缓存,再次构建镜像时,如果没有改动会复用缓存结果,因此指令的顺序很重要,前面的指令有改变,后面会全部重新build,所以应该把最不易更改的指令放在前面
25:compose使用技巧
- 端口绑定;8000:3000形式实际上是 0.0.0.0:8000:3000;表示任意机器都能访问本机的8000端口;很多时候我们不能希望暴露服务端口,希望只有本机能访问,这时候我们应该写成:127.0.0.1:8000:3000
- 查看日志:在项目中,使用 docker-compose logs 可以查看一个compose项目的日志;使用 docker-compose logs pyweb 的形式可以只查看某个特定服务的
- compose的多文件和覆盖配置:当我们使用docker-compose up启动compose项目的时候,实际上相当于 docker-compose -f docker-compose.yml up
我们可以用多个不同的compose配置文件来实现不同的启动方式;可以用init.yml
用于初始化,可以用debug.yml用于启动调试模式
docker-compose -f docker-compose.yml -f debug.yml up
26:开发部署
项目的开发和部署需要不同的设置,我们通常会使用不同的环境变量来配置环境
27:docker 其它用法
- 用docker来发布C C++或者其它平台相关的软件,可以让mac win用户都可以使用Linux软件
- 同时使用多个软件的不同版本
- 用于快速,方便安装一些服务,例如gogs:
docker run -p 3000:3000 gogs/gogs:latest