0%

docker笔记

docker 好处

1, 统一环境,标准化部署
不同服务器的安装运行环境是不一样的,
有些源不能及时更新,安装某些新软件甚至要手动编译

2, 解决依赖问题
不同微服务使用了不同的依赖,相互冲突

3, 隔离应用的运行环境
解决某些应用(redis)因为漏洞,导致服务器权限被他人获取

4, 更轻量的虚拟环境

启动容器

1
2
3
4
5
6
7
docker run -d -t -p 8000:5000 --name demo ubuntu:18.04

-d 后台
-t 让一个空白的ubuntu镜像在后台运行
-p 端口映射
--name demo 指定容器名
ubuntu:18.04 启动容器使用的镜像名, 没有的话, docker会自动从镜像服务器下载这个镜像

容器中安装软件

1
2
3
docker exec demo apt update
docker exec demo apt -y install python3 python3-pip
docker exec demo apt pip3 install flask

容器中启动应用

1
2
3
4
docker exec demo mkdir /code
docker cp a.py "demo:/code/a.py"
docker exec demo python3 /code/a.py

分别是: 在这个叫 demo 的容器中, 新建一个叫 code 的文件夹; 将当前目录下的 a.py 拷贝到容器的 code 文件夹中; 在容器中运行这个 a.py 文件

浏览器打开localhost:8000, 可以看到打印输出 Hello from Docker

a.py参考

1
2
3
4
5
6
7
8
9
10
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
return 'Hello from Docker'

if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)

用简单的脚本代替上面的工作

1, 编写两个脚本

install.sh

1
2
3
apt update
apt -y install python3 python3-pip
apt pip3 install flask

run.sh

1
2
cd /code 
python3 a.py

2, 执行

1
2
3
4
5
6
7
8
docker run -d -t -p 3333:8000 --name demo1 ubuntu:18.04

docker exec demo1 mkdir /code
docker cp a.py "demo1:/code/a.py"
docker cp run.sh "demo1:/code/run.sh"
docker cp install.sh "demo1:/code/install.sh"
docker exec demo1 bash /code/install.sh
docker exec demo1 bash /code/run.sh

其它常用命令

除了

1
2
3
4
docker run 创建
docker exec 运行命令
docker stop 停止
docker rm 删除

常用命令还有

1
2
3
docker ps 列举
docker ps -a 列举所有
docker start 运行容器(容器正在运行, 再次运行这个命令并不会报错)

总结

用脚本重复上面的步骤也是很繁琐的, 后面我们开始用 Dockerfile 来配置这些重复操作


Dockerfile文件

通过 Dockerfile 配置文件来执行 docker 相关操作, 比如构建自定义Docker镜像, 取代安装软件, 执行服务等相关操作

./Dockerfile

1
2
3
4
5
6
7
8
FROM ubuntu:18.04
RUN apt update
RUN apt -y install python3 python3-pip
RUN apt pip3 install flask
COPY app.py /code/app.py
WORKDIR /code
CMD ["python3", "app.py"]

FROM 指定基础镜像
RUN 构建镜像时要执行的命令
COPY 拷贝当前目录文件, 到docker容器中, 不同于命令 docker cp, COPY会自动在docker创建不存在的文件夹
WORKDIR 命令运行的默认目录
CMD 容器运行后要执行的命令, 值得注意的是, 这些命令都是在 WORKDIR 指定的默认目录中运行的

常用命令中还有个ENTRYPOINT命令, 用于指定容器运行后的入口程序, 意义比较小

使用Dockerfile

1, 在编辑好的Dockerfile文件目录下(要进行拷贝的app.py文件也要拷贝到当前目录), 我们运行

1
docker build -p webimage .

build 构建
-p webimage 指定构建的镜像名字, 方便以后使用
. 当前目录为执行环境

2, 完成后, 我们使用下面的命令, 查看目前所拥有的镜像

1
docker images

3, 使用创建好的镜像,启动一个容器, 我们叫它 demo2

1
docker run -d -t -p 3333:8000 --name demo2 webimage

至此, 我们就将之前的操作, 全部封装到了一个 叫 webimage 的镜像中, 下次我们在进行这些操作时, 只需要使用这个镜像, 去启动一个容器即可

服务器简单上传部署

1, 使用 scp 命令上传文件夹(文件夹内包含Dockerfile, a.py 等 )

1
scp -P 29337 -r app root@ip:/tmp

-P 29337 指定ssh端口(默认是22的不需要指定, 注意P是大写)

2, 然后 ssh 登陆

1
ssh -p 29337 root@ip

-p 29337 指定ssh端口(默认是22的不需要指定, 注意p是小写)

3, 进入/tmp/app目录, 执行命令生成 webimage 镜像(服务器上操作需要添加 sudo)

1
sudo docker build -t webimage .

4, 最后使用 webimage 镜像生成容器

1
sodo docker run -d -p 8000:5000 --name serverdemo webimage

5, 最后, 我们可以打开本地浏览器, 可以访问 服务器ip:8000

总结

这样生成容器是方便了, 但是每次都要手动把文件上传, 很繁琐, 暂且搁下, 在说这个之前, 先说一下 docker 的数据共享问题


数据卷

1, 容器之间数据是不通的, 删除容器后数据都会丢失, 所以docker引入了数据卷(volume)

2, 不同容器可以使用, 同一数据卷存储, 备份, 共享数据

3, 删除容器后, 挂载的数据卷不会删除

数据卷使用

1, 创建, 删除, 列举数据卷

1
2
3
docker volume create web
docker volume rm web
docker volume ls

2, 挂载数据卷

1
docker run -d --name serverdemo2 --mount source=web,target=/volume webimage

source=web 使用叫web的这个数据卷
target=/volume 挂在到/volume目录下

数据卷特性演示

1, 现在生成一个容器, 叫做demo, 并挂载一个数据卷 web到 volume目录下

1
docker run -d --name demo --mount source=web,target=volume webimage

2, 我们使用两种不同的方式保存demo产生的数据

1
2
docker exec demo sh -c "date > /b.txt"
docker exec demo sh -c "date > /volume/c.txt"

3, 当我们删除容器demo后, b.txt也会被删除, 但是c.txt不会被删除, 我们可以打印出来

1
docker exec demo sh -c "cat /volume/c.txt"

4, 多容器共享数据, 我们只需要这样声明新容器 demo2

1
docker run -d --name demo2 --mount source=web,target=v2 webimage

这时候, 尽管demo2还没有生成数据, 但是执行下面的cat命令, 却打印出了数据
docker exec demo2 sh -c “cat /v2/c.txt”