Toc
  1. 一. Docker基础篇:
  2. 二. Docker高级篇
Toc
0 results found
Goblin
Docker怎么玩~
2020/03/31 Code 干货 笔记

一. Docker基础篇:

Docker的三大要素:

  1. 镜像-只读的原本 类比java的类
  2. 容器-一个个在Docker中跑的程序(nginx, redis等) 类比java类创建出的实例
  3. 仓库-可以把打包好的镜像上传到DockerHub, 运维可以直接下载(国外的网站太慢, 用不到)

虚拟机和Docker的区别:

CentOS/ Ubuntu基础镜像仅170MB 而虚拟机的镜像系统要4个G(同时模拟了硬件)

docker(容器虚拟化技术) 虚拟机技术
操作系统 与宿主机共享, docker引擎调节 宿主机os上运行虚拟机os
储存大小 镜像小, 便于传输(Mb) 镜像大(G)
运行性能 几乎无额外性能损失 操作系统消耗额外cpu
移植性 轻便灵活 与虚拟化技术耦合
硬件亲和性 面向软件开发 面向运维
部署速度 秒级 分钟级(10s+)

开发/运维: DevOps 一次构建, 随处运行

Docker的架构图:

图片

从远程Registry拉取到本地, 就是一个Images镜像, 这个镜像的实例就是一个Containers容器

镜像就是模板, 容器就是这个镜像的实例. 一个镜像可以创建很多容器. 可以把容器看成一个简易版的Linux环境, 和运行在其中的应用程序. 仓库是集中存放镜像文件的场所

Repository仓库和Registry仓库注册服务器是有区别的.

仓库注册服务器上往往存放着多个仓库, 每个仓库中又包含了多个镜像, 每个镜像有不同的标签(tag)

仓库又分为公开仓库和私有仓库. 两种形式, 世界最大公开仓库DockerHub, 国内的公开仓库 阿里云.

Docker安装的官方文档: 安装就看他

https://docs.docker.com/install/linux/docker-ce/centos/

阿里云镜像加速的配置文档: 配置阿里仓库就看他

https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

专属加速地址

https://ld9eyi9w.mirror.aliyuncs.com

Docker指令之helloworld:

docker run hello-world
先在本地找, hello-world的镜像
->没有, 去远程拉取pulling

图片

流程图:

图片

docker命令:

1. docker -version 版本信息
2. docker info 详细信息
3. docker --help 常用命令
4. docker images 当前主机能运行的镜像模板
REPOSITORY: 镜像的仓库源
TAG: 版本
IMAGE ID: 镜像的唯一ID
CREATED: 创建时间
SIZE : 大小
5. docker search 去dockerhub查找(配置了镜像也是从dockerhub查询, 只是下载的时候去阿里云下载而已)
6. docker pull 下载镜像
7. docker rmi -f 镜像名 镜像名 镜像名... 删除镜像
清盘删除: docker rmi -f $(docker images -qa)
$() 相当于 取出后面的docker images -qa的结果当做参数

图片

tomcat为什么这么大呢?

8. docker run -it 470671670cac

图片

9. docker ps     列出所有运行的容器
10. exit 关闭容器并退出命令行
ctrl + p 再按 ctrl + q 不关闭容器, 先离开一会终端
11. docker stop 停止容器 温柔关闭
12. docker kill 直接杀死容器
13. docker rm [-f] 容器号 删除容器 -f是强制删除(可删除正在运行的容器)
docker rm -f $(docker ps -qa) 批量删除
或docker ps -qa | xargs docker rm
linux命令, 管道符左边的结果当做参数传入右边的命令
docker run -d : 后台守护线程形式运行应用
docker run -d centos /bin/sh -c "while true;do echo hello zzyy;sleep 2; done"

使用镜像centos以后台模式启动一个容器:
$ docker run -d centos
然后
$ docker ps -a 进行查看, 会发现容器已经退出
因为:
Docker容器后台运行, 就必须有一个前台进程, 否则会自动退出
这个是Docker的机制问题:
比如nginx 我们配置启动服务只需要启动响应的service即可, 例如service nginx start
但是这样 nginx为后台进程模式运行, 就会docker前台没有对应运行的应用.
这样容器后台一启动, 就会立即自杀, 因为觉得自己没事做了.
所以: 要将后台运行的程序以前台进程的形式运行

docker run -it centos /bin/bash 后面的 bin/bash的作用

(https://www.cnblogs.com/Guhongying/p/10894434.html)

首先,docker run -it centos 的意思是,为centos这个镜像创建一个容器, -i和-t这两个参数的作用是,为该docker创建一个伪终端,这样就可以进入到容器的交互模式?(也就是直接进入到容器里面)后面的/bin/bash的作用是表示载入容器后运行bash ,docker中必须要保持一个进程的运行,要不然整个容器启动后就会马上kill itself,这样当你使用docker ps 查看启动的容器时,就会发现你刚刚创建的那个容器并不在已启动的容器队列中。这个/bin/bash就表示启动容器后启动bash。

14. docker logs [参数] 容器id   查看日志
-f 跟随最新日志打印
-t 加入时间戳
--tail 显示最后多少条
eg: docker logs -t -f --tail 3 7e0b062af691
15. docker top  容器id       查看容器内运行的进程
16. docker inspect 容器id 查看容器的细节

比如:

[
    {
        "Id": "7e0b062af6916144a33118a1",
        "Created": "2020-03-27T05:21:24.424453733Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo hello zzyy;sleep 2; done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 16750,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-03-27T05:21:24.799995316Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:...",
        "ResolvConfPath": "",
        "HostnamePath": "",
        "HostsPath": "",
        "LogPath": "",
        "Name": "/crazy_fermi",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Capabilities": null,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "",
                "MergedDir": "",
                "UpperDir": "",
                "WorkDir": ""
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "7e0b062af691",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "while true;do ech"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20200114",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS",
                "org.opencontainers.image.created": "2020-01-",
                "org.opencontainers.image.licenses": "GPL-2.0-only",
                "org.opencontainers.image.title": "CentOS Base Image",
                "org.opencontainers.image.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "3459bdd5aa27c479a87",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/3459bdd5aa27",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "e519bb72809ee6f974029",
            "Gateway": "172.18.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.18.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:12:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "126cf7e01e7d170ed",
                    "EndpointID": "e519bb728",
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:12:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
17. docker attach 容器id  进入正在运行的容器并以命令行进行交互
直接进入容器启动命令的终端, 不做任何事
docker exec -it 容器id [/bin/bash ...] 在容器外执行, 既可以进去干, 还可以打开新进程(直接操作 隔山打牛的效果)

18. docker cp 容器id:容器内路径 目的主机路径 拷贝容器内文件到主机上

二. Docker高级篇

  1. Docker镜像是什么:

轻量级的可执行的独立软件包, 用来打包软件运行环境和基于运行环境开发的软件, 它包含某个软件所需的所有内容, 包括代码, 运行时库, 环境变量, 和配置文件

UnionFS联合文件系统: 分层的轻量级高性能的文件系统.

图片

Docker镜像加载原理: docker镜像实际上由一层层的文件系统组成,

bootfs: 主要包含bootloader和kernel, bootloader主要是引导加载kernel, linux刚启动时会加载bootfs文件系统, 在docker镜像的最底层是bootfs, 当boot加载完成后整个内核就都在内存中了, 此时内存的使用权已由bootfs转交给内核, 此时系统也会卸载bootfs

rootfs: 在bootfs上, 包含的就是典型linux系统中的/dev, /proc, /bin等标准目录和文档, rootfs就是不同操作系统的发行版, 比如ubuntu centos等.

图片

图片

tomcat 比centos还大的原因

docker采用分层镜像的原因: 共享资源

多个镜像都从相同的base镜像构建而来, 这样每个镜像的每一层都可被共享.

docker的镜像都是只读的, 当容器启动时, 一个新的可写层被加载到 镜像的顶部, 这一层 通常被成为容器层, 容器层之下的都叫镜像层.

  1. docker 的commit

我们对一个源镜像, 进行了自定义的修改和配置后, 得到了我们专属的容器, 那么怎么把这个容器分享给他人, 使得他人启动这个容器和我们启动这个容器达到一样的效果呢?

这里就可以用commit命令.

docker commit -a="goblin" -m="my images" 78sd7f8 mytomcat:v1.0 
-a: author 作者
-m: 容器信息
要制作镜像的容器id
新镜像的名字:Tag(版本)
  1. docker容器数据卷:

当我们关闭容器后, 容器内的数据就没了, 那么我们关闭容器时, 需要对容器内产生的数据进行持久化. 这个要持久的数据就是数据卷.

k将运用与运行的环境打包形成容器运行, 运行可以伴随着容器, 但是我们对数据的要求希望是持久化的

容器之间希望有可能共享数据

Docker容器产生数据, 如果不通过docker commit生成新的镜像, 使得数据作为镜像一部分保存下来, 那么当容器删除后, 数据也就没了.

为了能保存数据在docker中, 我们使用卷

目的就是: 持久化和数据共享

@1: 可以使用命令行

1. 在容器上建立文件夹挂载到主机上, 二者实时共享, 均可读写
docker run -it -v /myDataVolumn:/dataVolumnContainer 镜像名
2. 将容器上的文件夹/dataVolumnContainer(绝对路径)挂载到主机的/myDataVolumn, 容器只读: 容器只能查看主机传给他的文件, 自己不能写操作
docker run -it -v /myDataVolumn:/dataVolumnContainer:ro 镜像名 (readonly)

@2. 通过dockerfile

dockerfile是对镜像 源码级 的描述,

打赏
支付宝
微信
本文作者:Goblin
版权声明:本文首发于Goblin的博客,转载请注明出处!