环境:下载Docker Desktop 就可以使用docker了
目标:在idea中可以将应用image推送到本地docker里
docker 三要素:镜像(image)、容器(contarin)、registry(包含多个仓库)
- 查看版本
docker --version
docker info
- 查看正在运行的容器实例
docker container ls
docker exec -it docker-ignite-1 /bin/sh
- 显示完整的列值 docker ps 罗列的是当前活跃的容器。
docker ps --no-trunc
- 查看所有容器执行
dokcer ps -a
- 执行容器内部命令
docker exec -it [CONTAINER ID] /bin/bash
- 退出容器
exit
- 将docker内部文件拷贝到主机目录上
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
命令 | 作用 |
docker | 帮助 |
docker start/stop/restart/kill | 启动 / 停止 / 重启 / 杀掉容器 |
docker run | 创建并启动一个新的容器 |
docker rm | 删除容器 |
docker create | 创建一个新的容器但不启用它 |
docker exec | 在运行的容器中执行命令 |
docker ps | 列出正在运行的容器 |
docker inspect | 获取容器的元数据 |
docker logs | 获取容器的日志 |
docker port | 显示指定容器的端口映射 |
docker commit | 用已存在的容器重新创建一个新的镜像 |
docker cp | 用于容器与物理主机之间拷贝文件 |
docker login/logout | 用于登录与登出容器镜像仓库 |
docker pull/push | 从镜像仓库中拉取或者指定更新镜像 / 将本地的镜像上传到镜像仓库,要先登录到镜像仓库 |
docker images | 显示系统本地容器镜像文件 |
docker rmi | 删除镜像 |
docker tag | 标记本地镜像 |
docker history | 查看指定镜像的创建历史 |
docker info | 显示 docker 系统信息,包括镜像和容器数 |
docker version | 显示 docker 版本信息 |
- 运行镜像文件,创建容器,启动程序
docker run -it -d -p 18020:18020 --name=config-center 90d4f46db3a6 (image id) /bin
docker run -i -d --name=data-persistence db47cb6bd41d
- 运行镜像并进入容器
docker run -it --rm ubuntu:18.04 bash
docker run 就是运行容器的命令,后面如果只跟镜像,那么就执行镜像的默认命令然
后退出。
-it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入
bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
--rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的
容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结
果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash。
进入容器后,我们可以在 Shell 下操作,执行任何所需的命令。通过 exit 退出。
10启动容器
Docker start 容器id
- 停止容器
Docker stop 容器id
- 结束掉容器
docker kill [CONTAINER ID]
- 移除容器
Docker rm 容器id
- 运行程序内部命令,注意sh脚本使用./和sh的问题
docker exec -it 67b810a48bf5 ./apache-ignite/bin/sqlline.sh --verbose=true -u jdbc:ignite:thin://127.0.0.1/
- 运行程序内部命令,cat查询文件内容
docker exec -it 67b810a48bf5 cat apache-ignite/bin/control.sh
- 查看docker上运行java程序日志(data-p为容器names)
docker logs -f -t --tail 100 data-p
- docker maven 使用 docker-maven-plugin 自动生成镜像并推送到仓库中
mvn clean package docker:build -DskipTests -DpushImageTags -DdockerImageTags=data-p2
18 docker restart container-id 重新启动容器应用
相当于先执行 stop 在执行start
19 docker中如何查看应用占用资源情况
docker stats
20 日志打印
docker logs CONTAINER_ID | grep -10 'error' # 打印匹配行的前后10行
docker logs CONTAINER_ID | grep -C 10 'error' # 打印匹配行的前后10行
docker logs CONTAINER_ID | grep -A 10 -B 10 'error' # 打印匹配行的前后10行
docker logs CONTAINER_ID | grep -A 10 'error' # 打印匹配行的后10行
docker logs CONTAINER_ID | grep -B 10 'error' # 打印匹配行的前10行
21 常用运行应用命令(重复)
docker run -it -d -p 18080:18080 --name=msg-1 e31185869264
docker run -it -d -p 18060:18060--name=task-8 6ec991406aa4
22 应用使用nacos,启动服务
docker pull nacos/nacos-server:v2.2.0
docker run --name nacos-quick -e MODE=standalone -p 8849:8848 -d nacos/nacos-server:2.2.0
访问地址http://127.0.0.1:8848/nacos/
22 docker logs : 获取容器的日志
语法
docker logs [OPTIONS] CONTAINER
OPTIONS说明:
-f : 跟踪日志输出
--since :显示某个开始时间的所有日志
-t : 显示时间戳
--tail :仅列出最新N条容器日志
实例
跟踪查看容器mynginx的日志输出。
runoob@runoob:~$ docker logs -f mynginx192.168.239.1 - - [10/Jul/2016:16:53:33 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"2016/07/10 16:53:33 [error] 5#5: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.239.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.239.130", referrer: "http://192.168.239.130/"192.168.239.1 - - [10/Jul/2016:16:53:33 +0000] "GET /favicon.ico HTTP/1.1" 404 571 "http://192.168.239.130/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"192.168.239.1 - - [10/Jul/2016:16:53:59 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"...
查看容器mynginx从2016年7月1日后的最新10条日志。
docker logs --since="2016-07-01" --tail=10 mynginx
23重命名images
docker tag registry.gv/gv/service/msg-persistence:2.0.0 registry.gv/gv/service/msg-persistence:v1
docker tag registry.gv/gv/service/task-management:1.0.0 registry.gv/gv/service/task-management:v2
24 将images推送到harbor仓库
docker push registry.gv/gv/service/msg-persistence:v1
25 拉取使用
docker pull registry.gv/gv/service/msg-persistence:v1
什么是docker?
要解释清楚Docker,首先要说解释清楚容器(Container)的概念。要解释容器的话,需要从操作系统说起。太深入的一两本书都说不清楚,直接引用维基的说法,操作系统就是管理计算机的硬件软件和资源,并且为软件运行提供通用服务的系统软件。
- 硬件管理,包括分配CPU时间、内存;从网络、存储设备等IO设备读写数据。
- 软件管理,就是各种软件的运行,线程、进程调度之类的工作。
- 为软件提供运行环境,这个运行环境通常一部分由操作系统内核(Kernel)提供,另一部分由运行库(Runtime Library)提供。
硬件、操作系统、应用程序之间的关系可以简单的用下图表示:
+--------------------------+
| Applications |
+--------------------------+
|+------------------------+|
|| Runtime Library ||
|+------------------------+|
|| Kernel ||
|+------------------------+|
| Operating System |
+-----+--------+-----------+
| CPU | Memory | IO Device |
+-----+--------+-----------+
随着硬件的性能提升,以及软件种类的丰富,有两种情况变得很常见:
- 硬件性能过剩——很多计算机的硬件配置,即使不能完全满足峰值性能的要求,也往往会有大量时间处于硬件资源闲置的状态。例如一般家用电脑,已经是四核、六核的配置了,除了3A游戏、视频制作、3D渲染、高性能计算等特殊应用外,通常有90%以上时间CPU是闲置的。
- 软件冲突——因为业务需要,两个或者多个软件之间冲突,或者需要同一个软件的不同版本。例如早几年做web前端的,要测试网页在不同版本的IE上是否能正常显示,然而Windows只能装一个版本的IE。
为了解决软件冲突,只能配置多台计算机,或者很麻烦的在同一台电脑上安装多个操作系统,通过重启来进行切换。显然这两个方案都有其缺点:多台计算机成本太高,多操作系统的安装、切换都很麻烦。在硬件性能过剩的时候,硬件虚拟化的普及就很自然而然的提出来了。
所谓硬件虚拟化,就是某个特殊的软件,仿真出一台或者多台计算机的各种硬件,用户可以在这一台虚拟机上安装、运行操作系统(一般叫来宾操作系统,Guest OS)和各种应用,并且把Guest OS和上面应用软件对硬件资源的访问转发到底层的硬件上来实现。对于Guest OS和上面的应用程序来说,这台虚拟机和普通的物理计算机是完全一样没有任何区别的——除了性能可能差一点。著名的VMware就是这么一个软件,这类软件英语有一个专用的单词是Hypervisor(维基的Hypervisor词条说另一种叫法是虚拟机监视器,Virtual Machine Monitor,vmm。但我个人觉得叫虚拟机管理器,Virtual Machine Manager,更合适一点,虽然可能会和微软的System Center Virtual Machine Manager以及Redhat的Virtual Machine Manager这两个软件混淆),中文大概应该叫虚拟化软件/应用之类的。
Hypervisor根据其对硬件资源的访问方式,可以分为两大类,Type I是Hypervisor直接访问硬件资源,通常会有另一个操作系统运行于Hypervisor之上来对硬件资源,例如VMware EXSi,Windows的Hyper-V,Linux的Xen;Type II是Hypervisor和普通的应用一样,运行在某个操作系统(例如Windows或者Linux等,这里称之为宿主机操作系统,Host OS)之上,Hypervisor通过Host OS访问硬件资源,例如VMware Workstation,Virtual Box等。两种类型的Hypervisor区别如图所示。
+-----+-----+-----+-----+
|App A|App B|App C|App D|
+-----+-----+-----+-----+ +-----+-----+-----+-----+
|App A|App B|App C|App D| |Guest|Guest|Guest|Guest|
+-----+-----+-----+-----+ | OS0 | OS1 | OS2 | OS3 |
|Guest|Guest|Guest|Guest| +-----+-----+-----+-----+
| OS0 | OS1 | OS2 | OS3 | | Hypervisor |
+-----+-----+-----+-----+ +-----------------------+
| Hypervisor | | Host OS |
+-----------------------+ +-----------------------+
| Hardware | | Hardware |
+-----------------------+ +-----------------------+
Type I Type II
虚拟机的一个缺点在于Guest OS通常会占用不少硬件资源。例如Windows安装开机不运行任何运用,就需要占用2~3G内存,20~30G硬盘空间。即使是没有图形界面的Linux,根据发行版以及安装软件的不同也会占用100~1G内存,1~4G硬盘空间。而且为了应用系统运行的性能,往往还要给每台虚拟机留出更多的内存容量。虽然不少Hypervisor支持动态内存,但基本上都会降低虚拟机的性能。如果说这样的资源占用少量的虚拟机还可以接受的话,同时运行十数台数十台虚拟机的时候,浪费的硬件资源就相当可观了。通常来说,其中相当大部分甚至全部Guest OS都是相同的。
能不能所有的应用使用同一个的操作系统减少硬件资源的浪费,但是又能避免包括运行库运行库在内的软件冲突呢?操作系统层虚拟化——容器概念的提出,就是为了解决这个问题。在Linux可以通过控制组(Control Group,通常简写为cgroup)隔离,并把应用和运行库打包在一起,来实现这个目的。容器和Type II虚拟机、物理机的区别见下图:
+-----+-----+-----+-----+ +-----+-----+-----+-----+
|App A|App B|App C|App D| +-----+-----+-----+-----+ |App A|App B|App C|App D|
+-----+-----+-----+-----+ |App A|App B|App C|App D| +-----+-----+-----+-----+
|+---------------------+| +-----+-----+-----+-----+ |Guest|Guest|Guest|Guest|
|| Runtime Library || |Lib A|Lib B|Lib C|Lib D| | OS0 | OS1 | OS2 | OS3 |
|+---------------------+| +-----+-----+-----+-----+ +-----+-----+-----+-----+
|| Kernel || | Container Engine | | Hypervisor |
|+---------------------+| +-----------------------+ +-----------------------+
| Operating System | | Host OS | | Host OS |
+-----------------------+ +-----------------------+ +-----------------------+
| Hardware | | Hardware | | Hardware |
+-----------------------+ +-----------------------+ +-----------------------+
Physical Machine Container Type II Hypervisor
上图中,每一个App和Lib的组合,就是一个容器。也就是Docker图标里面的一个集装箱。和虚拟机相比,容器有以下优点:
- 迅速启动:没有虚拟机硬件的初始化,没有Guest OS的启动过程,可以节约很多启动时间,这就是容器的“开箱即用”。
- 占用资源少:没有运行Guest OS所需的内存开销,无需为虚拟机预留运行内存,无需安装、运行App不需要的运行库/操作系统服务,内存占用、存储空间占用都小的多。相同配置的服务器,如果运行虚拟机只能运行十多台的,通常可以运行上百个容器毫无压力——当然前提是单个容器应用本身不会消耗太多资源。
当然,和虚拟机相比,因为共用内核,只靠cgroup隔离,应用之间的隔离是不如虚拟机彻底的,如果某个应用运行时导致内核崩溃,所有的容器都会崩溃。而虚拟机内的应用崩溃,理论上是不会影响其它虚拟机以及上面运行的应用的,除非是硬件或者Hypervisor有Bug。
Docker把App和Lib的文件打包成为一个镜像,并且采用类似多次快照的存储技术,例如aufs/device mapper/btrfs/zfs等,可以实现:
- 多个App可以共用相同的底层镜像(初始的操作系统镜像)
- App运行时的IO操作和镜像文件隔离;
- 通过挂载包含不同配置/数据文件的目录或者卷(Volume),单个App镜像可以同时用来运行无数个不同业务的容器。
+---------+ +---------+ +---------+ +-----+ +-----+ +-----+
| abc.com | | def.com | | xyz.com | | DB1 | | DB2 | | DB3 |
+----+----+ +----+----+ +----+----+ +--+--+ +--+--+ +--+--+
| | | | | |
+----+----+ +----+----+ +----+----+ +--+--+ +--+--+ +--+--+
| abc | | def.com | | xyz.com | | DB1 | | DB2 | | DB3 |
| config | | config | | config | | conf| | conf| | conf|
| data | | data | | data | | data| | data| | data|
+----+----+ +----+----+ +----+----+ +--+--+ +--+--+ +--+--+
| | | | | |
+------------+------------+ +-------+-------+
| |
+------+------+ +------+------+
| Nginx Image | | MySQL Image |
+------+------+ +------+------+
| |
+----------------+----------------+
|
+------+-------+
| Alpine Image |
+------+-------+
上图是基于一个Alpine Linux的镜像,分别建立了Nginx和MySQL的镜像,并且挂载不同的配置/数据同时运行3个网站应用3个数据库应用的示意图。
此外,Docker公司提供公共的镜像仓库(Docker称之为Repository),Github connect,自动构建镜像,大大简化了应用分发、部署、升级流程。加上Docker可以非常方便的建立各种自定义的镜像文件,这些都是Docker成为最流行的容器技术的重要因素。
通过以上这些技术的组合,最后的结果就是,绝大部分应用,开发者都可以通过docker build创建镜像,通过docker push上传镜像,用户通过docker pull下载镜像,用docker run运行应用。用户不需要再去关心如何搭建环境,如何安装,如何解决不同发行版的库冲突——而且通常不会需要消耗更多的硬件资源,不会明显降低性能。这就是其他答主所说的标准化、集装箱的原因所在。
题外话:除了Docker以外,还有其它很多种容器,例如Linux上的LXC、OpenVZ,FreeBSD的Jail,Solaris的Zones等等。此外,Unix-Like操作系统的chroot命令从某种角度来说也是一种特殊的容器实现方式。和*nix采用宏内核,且内核和各种运行库耦合松散,很方便实现容器不同,Windows因为采用微内核,且内核与各种运行库耦合紧密,虽然从Windows 10/2016开始也支持容器,但事实上还是通过Hyper-V运行不同的虚拟机进行内核级隔离——虽然也有线程级的隔离,但只有Windows Server支持,并且只能运行相同版本的镜像[1]。而且即使是Hyper-V,也只支持运行更低版本的镜像而不能运行更高版本的镜像。另外Windows容器的镜像体积通常还是很大。