@author: Basil Guo @date: Dec. 11, 2020 @desc: docker的简单使用
由于参考书目的原因,所有的命令请参考这个网站: https://docs.docker.com/engine/reference/commandline/docker/
1. 简介
1.1. 历史
虚拟化技术很早就出现了,不过一般都是主机级别的虚拟化,虚拟机技术,此处分为1类和2类。
- 1类:所有的os都运行于虚拟机上,例如hypervisor
- 2类:在OS上开虚拟机,如vmware
但是上述主机级别的虚拟化都很占用资源,毕竟运行OS的资源是需要很多的,而如果上面只是运行少部分的应用,非常浪费,这里将会用到的是应用级别的虚拟化。
Docker是dotCloud公司开源小项目,用于创建、管理和编排容器。docker一词来源于英国口语:dock worker,码头工人。运行中的容器共享宿主机的内核。
Docker引擎是用于运行和编排容器的基础设施工具。Docker公司的一个哲学是:含电池但是可拆卸。(Batteries included but removable)所有的模块都是可插拔的,但是也越来越不用插拔了,因为越来越好用了的。
现在Docker是Moby项目的一部分,在Github上开源。
1.2. Docker依赖的关键技术
- Cgroup(Control Group)
- Namespace
- Aufs
- 最原始最老的存储驱动,现在可以是Overlay2(未来的最佳选择)、Device Mapper、Btrfs和ZFS
- 可以通过
$ docker system info
查看
1.3. 开放容器计划
The Open Container Initiative(OCI)开放容器计划旨在对容器基础架构中的基础组件进行标准化的管理委员会,管理容器标准的轻量级的、敏捷型的委员会。
它的由来是CoreOS公司不喜欢Docker公司的行事方式(因为docker野心扩张危及到了前者在生态圈中的位置),然后创建了一个新的开源标准,称作appc,涉及镜像格式和容器运行时等方面,然后还开放了一个名为"rkt"(发音rocket,实则rock-it)的实现。没办法,没有标准就会撕裂,所以最后成立了OCI。
已有规范是镜像规范和运行时规范。
2. 安装与升级
2.1. Linux
2.1.1. Install Docker in Linux(Ubuntu)
$ curl -sSL https://get.docker.com/ | sh
- 或者
$ wget -q0- https://get.docker.com/ | sh
最好通过非root用户来使用Docker。这时需要添加非root用户到本地Docker Unix组当中。
$ sudo usermod -aG docker basil
$ cat /etc/group | grep docker
docker:x:998:basil
# verify
$ docker version
$ docker system info
2.1.2. Install Docker Compose in Linux
$ curl -L https://get.daocloud.io/docker/compose/releases/download/1.7.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
- You can change 1.7.1 to the version you need
$ chmod +x /usr/local/bin/docker-compose
- Let other user to use
$ docker-compose --version
- Verify docker-compose successfully installed
2.2. Docker for Windows
2.2.1. Prerequisite
- Windows 10 Pro / Enterprise / Education(1607Anniversary Update、Build 14393或者更新的版本)
- Windows必须是64位的版本
- 需要启用Windows操作系统中的Hyper-V和容器特性,即开启BIOS设置中的硬件虚拟化支持
- 控制面板→程序和功能→启用或关闭Windows功能→勾选“Hyper-V”和“容器”功能
2.3. Docker for Mac
Mac本身不支持容器,启动一个简单的Linux VM来运行Docker。Mac版本的Docker通过对外提供daemon和API的方式与Mac环境实现无缝集成。
2.4. 升级Docker引擎(Ubuntu 16.04)
- 停止Docker守护程序
- 移除旧版本的Docker
- 安装新版本的Docker
- 配置新版本的Docker为开机启动
- 确保容器重启成功
# 更新APT包列表
$ apt-get update
# 卸载当前的Docker
$ apt-get remove docker docker-engine docker-ce docker.io -y
# 安装新版本的Docker
$ wget -q0- https://get.docker.com/ | sh
# 设置为开机自启
$ systemctl enable docker
$ systemctl is-enabled docker
enabled
# 确保每个容器和服务都已经重启成功
$ docker container ls
$ docker service ls
2.5. Docker存储驱动的选择
每个Docker容器都有一个本地存储空间,用于保存层叠的镜像层(image layer)以及挂载的容器文件系统。默认情况下,容器的所有读写操作都发生在其镜像层上或挂载的文件系统中,所以存储是每个容器的性能和稳定性不可或缺的一个环节。
Windows上只有一个可选的Windows Filter。
Linux上Docker可选择的一些存储驱动包括AUFS(最原始也是最老的)、Overlay2(可能是未来的最佳选择)、DeviceMapper、Btrfs和ZFS。
存储驱动的选择是节点级别的。这意味着每个Docker主机只能选择一种存储驱动,而不能为每个容器选择不同的存储驱动。不过不知道这里主机指的是虚拟机还是物理机。
Linux上可以通过修改/etc/docker/daemon.json
文件来修改存储引擎配置,修改后要重启Docker才能生效。
{
"storage-driver" : "overlay2"
}
正在运行的Docker主机的存储引擎被修改了之后,现有镜像和容器在重启之后将不可用,因为每种存储驱动在主机上存储镜像层的位置是不同的(通常在/var/lib/docker/<storage-driver>/...
目录下)。修改了存储驱动的类型,Docker就无法找到原有的镜像和容器了。切换到原来的存储驱动,之前的镜像和容器就可以继续使用了。
当然可以先打包上传镜像,然后修改重启,再从镜像库拉取,重启容器就可以使用了。
请注意:切换别的存储引擎基本不需要配置,但是使用Driver Mapper则比较繁琐。具体细节参考官方文档^1
3. 剖析
开机启动
# 启动docker
systemctl start docker
# 停止docker
systemctl stop docker
# 开机自动启动
systemctl enable docker
# 禁止开机自启
systemctl disable docker
3.1. 运维视角
Docker可以分为客户端和Daemon(服务端或者说是引擎)。daemon实现了Docker引擎的API。默认情况下,Linux中客户端与Daemon的通信是基于IPC/Unix Socket完成的/var/run/docker.sock
;Windows中通过名为npipe:////.pipe/docker_engine
的管道完成的。
如果使用docker version
检测客户端和服务端都成功运行,并互相通信。
3.1.1. 镜像Image
Docker镜像可以理解为一个包含了OS文件系统和应用的对象。类似于虚拟机模板。镜像实际上在Docker世界中相当于是未运行的容器。
镜像需要从中央仓库获取,使用Linux,那么会拉取ubuntu:latest
镜像;如果使用Windows,则会拉取microsoft/powershell:nanoserver
镜像。
# 下载镜像 | 获取镜像
$ docker pull [从hub.daocloud.io获取的容器标签]
# 查看所有镜像
$ docker image ls # 相当于是docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
3.1.2. 容器Container
获取镜像之后需要启动,镜像类似于Class,而容器类似于Instance。
# 简单启动
docker run 镜像ID|镜像名称[:tag]
# 常用启动参数
# -d 后台运行 -p 端口映射 --name 指定容器的名称
docker run -d -p linux端口:容器端口 --name 容器名称 镜像ID
# 举例
docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=root334 daocloud.io/library/mysql:5.7.4
docker run -d -p 8080:8080 --name tomcat b8
# 访问:http://[ipv6]:8080
# 启动容器, -it参数会将Shell切换到容器终端
# Ctrl-PQ可使得退出容器同时还保证其在运行中
$ docker container run -it ubuntu:latest /bin/bash
root@f1f72097752f:/#
# 连接到运行中的容器
$ docker exec -it f1 bash
# 以下也是可以的,但是需要把container-name给改成docker ps后那个运行中容器的名字
$ docker exec -it <container-name> bash
# 查看运行中的容器
# 参数
# -a: 所有容器,默认只有运行中的,这个包括停止的
# -q: 只列出其Container ID
$ docker ps
# 或
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f1f72097752f ubuntu:latest "/bin/bash" 4 minutes ago Up 4 minutes infallible_dhawan
# 查看日志
$ docker logs -f 容器ID
# 停止指定容器
$ docker stop 容器ID
# 停止全部容器
$ docker stop $(docker ps -qa)
# 停止上述容器
$ docker stop f1
# 删除指定容器
$ docker rm 容器ID
# 删除全部容器
$ docker rm $(docker ps -qa)
# 移除容器(删除前先停止)
$ docker rm f1
# 宿主机内容复制到docker容器中
$ docker cp 文件名称 容器ID:路径
3.1.3. 数据卷
将宿主机的目录映射到docker容器中的一个目录(后续更改宿主机,就是相当于修改了容器)
# 1. 创建
# 创建数据卷之后,默认存放在宿主机的/var/lib/docker/volumes/数据卷名称/_data
docker volume create 数据卷名称
# 2. 查看详细信息
docker volume inspect 数据卷名称
# 3. 查看全部数据卷
docker volume ls
# 4. 删除
docker volume rm 数据卷名称
# 5. 指定路径
# 映射不存在时docker会自动创建
docker run -v 数据卷名称:容器内路径 镜像ID # 这种方式会将容器内部自带文件存储在默认的路径中
docker run -v 宿主机路径:容器内路径 镜像ID # 这种方式不会,路径下是空的
3.2. 开发视角
容器就是应用。
3.2.1. 自定义镜像
- 创建Dockerfile,指定镜像信息
# from:指定当前自定义镜像依赖的环境
# copy:将相对路径下的内容复制到自定义镜像中
# workdir:声明镜像的默认工作目录
# cmd:需要执行的命令,只以最后一个为准
# 举例
FROM daocloud.io/library/tomcat/8.5.15-jre8
COPY ssm.war /usr/local/tomcat/webapps
- 制作镜像
docker build -t 镜像名称:版本 目录 # 目录搞成当前目录'.'就好了
3.2.2. 举例
# 一份dockerfile示例
FROM alpine
LABEL maintainer="[email protected]"
RUN apk add --update nodejs nodejs-npm
COPY . /src
WORKDIR /src
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]
docker image build -t test:latest .
4. Docker-Compose
通过docker-compose编写docker运行参数
- 下载》
https://github.com/docker/compose/releases/download/1.24.1/docker-compose-Linux-x86_64
- 移动到
/usr/local/bin
- 改名字并给予可执行权限(2和3 可以通过软连接方式创建不是更好吗?)
- 修改环境变量:
vi /etc/profile
,export PATH=PATH:/usr/local/bin
4.1. 使用docker-compose管理容器
4.1.1. 编写docker-compose.yml文件
YAML文件:docker-compose.yml
文件,不要使用tab制表符代替空格
格式:key: value
方式来指定配置信息,多个配置信息使用换行和缩进的方式来进行区分
version: '3.1'
services:
mysql: # 服务的名称
restart: always # 代表只要docker启动,那么这个容器就跟着一起启动
image: daocloud.io/library/mysql5.7.4
container_name: mysql # 指定容器名称
ports:
- 3306: 3306 # 指定端口号映射
environment:
MYSQL_ROOT_PASSWORD: root # 指定MySQL 的ROOT用户登陆密码
TZ: Asia/Shanghai # 指定时区
volumes:
- /opt/docker_mysql_tomcat/mysql_data:/var/lib/mysql # 映射数据卷
tomcat:
restart: always
image: daocloud.io/library/tomcat:8.5.15-jre8
container_name: tomcat
ports:
- 8080:8080
environment:
TZ: Asia/Shanghai
volumes:
- /opt/docker_mysql_tomcat/tomcat_webapps:/var/local/tomcat/webapps
- /opt/docker_mysql_tomcat/tomcat_logs:/usr/local/tomcat/logs
4.1.2. 使用
使用docker-compose,默认会在当前目录下查找docker-compose.yml
文件
# 1. 基于docker-compose启动容器
docker-compose up -d
# 2. 关闭并删除容器
docker-compose down
# 3. 开启|关闭|重启已经存在的由docker-compose维护的容器
docker-compose start|stop|restart
# 4. 查看docker-compose管理的容器
docker-compose ps
# 5. 查看日志
docker-compose logs -f
4.2. docker-compose 配合Dockerfile使用
使用docker-compose.yml
文件以及Dockerfile
文件在生成自定义镜像的同时启动当前镜像,并且由docker-compose去管理容器
# yml文件
version: '3.1'
services:
ssm:
restart: always
build: # 构建自定义镜像
context: ../ # 指定dockerfile文件所在路径
dockerfile: Dockerfile # 指定Dockerfile文件名称
image: ssm:1.1.1
container_name: ssm
ports:
- 8081:8080
environment:
TZ: Asia/Shanghai
# Dockerfile文件
from daocloud.io/library/tomcat/8.5.15-jre8
copy ssm.war /usr/local/tomcat/webapps
# 进入docker-compose.yml文件所在的目录。
# 启动基于docker-compose.yml文件以及Dockerfile文件构建的自定义镜像
docker-compose up -d
# 如果自定义镜像不存在,会构建
# 如果镜像已存在,会使用以构建好的镜像
# 如果需要重新构建自定义镜像
docker-compose build
# 运行时,重新构建
docker-compose up -d --build
5. 参考
- Docker进阶与实战 | 华为Docker实践小组 | 2016
- Docker技术入门与实战 | 杨保华,戴王剑,曹亚仑 | 2018
- 深入浅出Docker | (英)奈吉尔·波尔顿 | 2019