Docker笔记
1. Docker简介
-
开源的应用容器引擎
-
打包环境和应用到一个轻量级,可移植的容器中,发布到任何 Linux 机器上,规避了软件跨环境迁移的问题
-
沙箱机制,相互隔离
1.1 安装
sudo apt install docker-ce
1.2 架构
-
守护进程(daemon):后台服务,管理一个 Docker 进程
-
镜像(image):相当于一个 root 文件系统,打包了环境和应用
-
容器(container):镜像运行时的实体,可以被创建,启动,暂停, 停止,删除
-
仓库(repository):保存镜像文件
2. Docker命令
2.1 服务(守护进程)相关
- 启动
sudo systemctl start docker
- 查看
sudo systemctl status docker
- 停止
sudo systemctl stop docker
- 重启
sudo systemctl restart docker
2.2 镜像相关
- 查看
sudo docker images
- 搜索
# 查看具体版本号需要去 hub.docker.com
sudo docker search ubuntu
- 拉取
# 配置阿里云加速://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
sudo vim /etc/docker/daemon.json
{
"registry-mirrors": ["加速地址"]
}
sudo systemctl daemon-reload
sudo systemctl restart docker
# 拉取镜像
sudo docker pull ubuntu[:版本]
- 删除
sudo docker rmi ubuntu[:版本]
2.3 容器相关
- 查看
# 要查看所有包括已停止运行的容器:加上参数 -a
sudo docker ps
- 创建
# -i:保持STDIN打开,-t:交互模式,bash:自定义进入容器后执行的命令
# -it 启动的容器称为交互式容器,exit 命令退出后容器会自动停止
sudo docker run -it --name u1 ubuntu[:版本] bash
# -d:后台创建容器,不会立即进入
# -id 启动的容器称为守护式容器,exit 退出时容器也不会自动停止
sudo docker run -id --name u1 ubuntu[:版本]
- 进入
# 只能进入正在运行的容器
sudo docker exec -it u1 bash
- 启动
# 这种方式启动容器后 exit 退出时也不会自动停止
sudo docker start u1
- 停止
sudo docker stop u1
- 删除
# 不能删除正在运行的容器
sudo docker rm u1
- 查看信息
sudo docker inspect u1
3. Docker数据卷
3.1 简介
- 宿主机中的一个目录(或文件),与容器内目录(文件)绑定后,同步它们的数据
- 可以被多个容器同时挂载,一个容器也可以挂载多个数据卷
- 数据持久化与数据交换
3.2 配置数据卷
# 创建启动容器时,-v 参数设置
# 容器内目录必须是绝对路径,宿主机目录可以相对,但相对的是 /var/lib/docker/volumes/,并不是当前路径
# 目录不存在会自动创建,而文件不存在时会被当成目录创建并挂载
# 可用多个 -v 挂载多个
sudo docker run ... -v 宿主目录(文件):容器内目录(文件) ... --name u1 ubuntu[:版本]
3.3 配置数据卷容器
配置一个专门的容器来挂载数据卷,其他容器挂载这个容器(这时候相当于挂载同一个数据卷)来交换数据
sudo docker run ... -v 宿主目录(文件):容器内目录(文件) ... --name u1 ubuntu[:版本]
# 其他容器挂载 u1
sudo docker run ... --volumes-from u1 --name u2 ubuntu[:版本]
sudo docker run ... --volumes-from u1 --name u3 ubuntu[:版本]
4. Docker应用部署
4.1 搜索并拉取镜像
sudo docker search mysql
sudo docker pull mysql:5.7
4.2 MySQL部署
# 宿主机创建MySQL目录用来存储数据信息
mkdir mysql
cd mysql
# 端口映射 宿主机:容器
sudo docker run -id \
-p 3306:3306 \
-v $PWD/conf.d:/etc/mysql.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=111 \
--name m1 mysql:5.7
4.3 Nginx部署
mkdir nginx
cd nginx
# 如果需要默认配置,可先启动一个容器将默认配置复制一份,否则宿主机空文件挂载后会覆盖容器内文件
# sudo docker cp n1:/etc/nginx/nginx.conf nginx.conf
sudo docker run -id \
-p 80:80 \
-v $PWD/nginx.conf:/etc/nginx/nginx.conf \
-v $PWD/conf.d:/etc/nginx/conf.d \
-v $PWD/logs:/var/log/nginx \
--name n1 nginx
5. Docker镜像制作
5.1 Docker镜像原理
- Docker镜像是由特殊的 文件系统 叠加 而成
- 最底端使用宿主机的bootfs
- 第二层是 rootfs,被称为基础镜像
- 最顶层为对外镜像名,下层镜像称为上层镜像的父镜像,下载时会把父镜像一并下载
- 统一文件系统将不同层整合成了一个文件系统,隐藏了多层的存在
- 镜像是只读的,从一个镜像启动容器时,会在顶层加载一个读写文件系统作为容器
5.2 方式一:容器转镜像
这种方式并不常用,因为打包后体积巨大不利于传递。
# 原容器中挂载的目录(文件)不会被提交到镜像
sudo docker commit 容器名(id) 镜像名[:版本号]
# 镜像打包
sudo docker save -o 文件名 镜像名[:版本号]
# 镜像还原
sudo docker load -i 文件名
5.3 方式二:Dockerfile
- 包含多条指令的文本文件
- 每条指令构建一层,基于基础镜像
- 提供完全一致的环境的构建方法
- 参照 hub.docker.com 上相关镜像的写法
- 构建
# 最后的 . 表示当前路径,是上下文目录,构建时会将路径下所有文件发给Docker引擎供 COPY ADD 等命令调用
# 如果配置文件名不为 Dockerfile,可用 -f 指定文件名
sudo docker build -t 新镜像名 .
5.4 Dockerfile常用关键字
- FROM:基于哪个基础镜像
- MAINTAINER:镜像维护者的姓名和邮箱地址
- WORKDIR:指定运行目录,为后续的 RUN、CMD、COPY、ADD 等命令配置工作目录,默认 /
- COPY:将宿主机的文件拷贝到镜像中去(原文件必须在build命令最后指定的路径内)
- ADD:和COPY一样,并且还可以解压缩,或者从url拷贝文件到镜像中
- RUN:构建镜像时运行的shell命令,由于DockerFile每条指令都会堆叠一层镜像,所以最好使用 \ 换行和 && 连接命令来减少体积
- EXPOSE:指定镜像暴露出来的端口
- CMD:容器运行时默认执行的shell命令(多个CMD只有最后一个生效)
- VOLUME:声明容器内多个路径为匿名卷,run容器时若没有指定宿主机目录与其关联,则自动在宿主机创建目录与其关联,目的是防止容器运行时产生太多数据,如 log
- ENV:指定环境变量
- USER:使用哪个用户启动,默认root
- ENTRYPOINT:和CMD一样,但是可以追加(必须使用exec格式:ENTRYPOINT [./entrypoint.sh,参数1,参数2……])
- LABEL:标签
- ONBUILD:当构建一个父镜像时,父镜像被子镜像继承时,ONBUILD被触发
6. 服务编排(Docker Compose)
微服务架构系统中一般包含多个微服务,每个微服务一般会部署多个实例,如果手动管理工作量就会很大:
- 要构建或拉取镜像
- 要创建多个容器
- 要管理这些容器
服务编排就是按照一定的规则批量管理容器的方法。Docker Compose 是一个编排多容器分布式部署的工具,提供命令集管理容器化应用的完整生命周期,使用步骤:
- 利用 DockerFile 定义运行环境镜像
- 使用 docker-compose 配置文件定义组成应用的各服务
- 运行 docker-compose up 启动应用
6.1 安装
sudo apt install docker-compose
6.2 编排一个 Nginx+Flask 项目
- 创建工作目录
mkdir project
cd project
# 创建nginx个人配置目录,一会儿做映射
mkdir -p nginx/conf.d
- 编写docker-compose配置文件
version: '3'
services:
# 定义一个容器
nginx1:
# 可以自定义容器名
container_name: main_nginx
image: nginx
ports:
- "80:80"
# 链接到另一个容器后便可以直接访问
links:
- flask1
# 这里简单起见对默认配置不做修改,仅挂载自定义配置
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
flask1:
container_name: main_flask
# 可以基于一份Dockerfile制作镜像并创建容器,如果同时指定image会以它命名镜像
# 这里假设已经在当前目录下写好了flask镜像的Dockerfile
build:
context: .
dockerfile: ./Dockerfile
image: img_flask
# 暴露端口,并没有与宿主机做映射,只允许被链接容器访问
expose:
- "8000"
# 如果容器内没有前台常驻进程,构建完后会立即退出,加上tty参数分配一个伪终端
# tty: true
- 编写Nginx程序配置 ./nginx/conf.d/flask1.conf
server {
listen 80; # 监听80端口来自外部的请求
server_name _; # 如果映射了域名,可以代替_
# 为HTTP规则 / 设置转发
location / {
proxy_pass //flask1:8000; # 转发到本地端口
}
}
- 启动
# 如果配置文件名不为 docker-compose.yml,可用 -f 指定文件名
# 后台启动 -d
sudo docker-compose up
- 查看所有容器状态
sudo docker-compose ps
- 停止容器
# 可通过 sudo docker-compose start 再次启动
sudo docker-compose stop
# 删除所有停止状态的容器
sudo docker-compose rm
# 停止并删除容器,网络
# --rmi all/local (删除compose文件中定义的所有镜像)/(删除镜像名为空的镜像)
# -v 删除已经在compose文件中定义的和匿名的挂载在容器上的数据卷
sudo docker-compose down