Docker为什么出现?

一款产品:开发—上线两套环境!应用环境,应用配置
开发 —— 运维 。问题:我在我的电脑上可以运行!版本更新,导致服务不可用,对于运维来说,考验十分大。
环境配置是非常麻烦的,每一个机器都要配置环境,费时费力。
发布一个项目,能不能都带上环境安装打包?

Docker给以上问题,提出了解决办法。
Docker的思想就来自于集装箱!
隔离是Docker核心思想,打包装箱,每个箱子都是互相隔离的。
Docker通过隔离机制,可以将服务器利用到机制。

Docker能干吗?

之前的虚拟机技术:

image.png
虚拟机技术缺点:
1、资源占用十分多
2、冗余步骤多
3、启动慢

容器化技术:

容器化技术不是模拟一个完整的操作系统
image.png

比较Docker和虚拟机技术的不同:
传统虚拟机:虚拟出一套硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟硬件,
每个容器是互相隔离的,每个容器内都有一个属于自己的文件系统,互不影响。

DevOps

应用更快速的交付和部署
传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行

更便捷的升级和扩缩容
使用了Docker之后,我们部署应用就和搭积木一样!项目打包为一个镜像,当在服务器A上性能出现瓶颈了,我们要扩展到服务器B上,做负载均衡,直接水平扩展到服务器B上一键运行。

更简单的系统运维
在容器化之后,我们的开发测试环境都是高度一致的。

更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上运行很多个容器实例,服务器的性能被压榨到极致。

Docker的基本组成

image.png

镜像(image):docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,例如通过tomcat镜像创建出tomcat01容器,这个容器提供服务器。
容器(container):Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建。启动停止删除还有基本命令。
目前就可以吧这个容器理解为一个建议的Linux系统

仓库(repository):
仓库就是存放镜像的地方

安装Docker

环境准备
1、Linux基础
2、CentOS 7
3、使用Xshell连接远程服务器进行操作!

环境查看

  1. 系统内核是3.10以上
  2. [root@localhost ~]# uname -r
  3. 3.10.0-862.el7.x86_64

系统版本

  1. [root@localhost ~]# cat /etc/os-release
  2. NAME="CentOS Linux"
  3. VERSION="7 (Core)"
  4. ID="centos"
  5. ID_LIKE="rhel fedora"
  6. VERSION_ID="7"
  7. PRETTY_NAME="CentOS Linux 7 (Core)"
  8. ANSI_COLOR="0;31"
  9. CPE_NAME="cpe:/o:centos:centos:7"
  10. HOME_URL="https://www.centos.org/"
  11. BUG_REPORT_URL="https://bugs.centos.org/"
  12. CENTOS_MANTISBT_PROJECT="CentOS-7"
  13. CENTOS_MANTISBT_PROJECT_VERSION="7"
  14. REDHAT_SUPPORT_PRODUCT="centos"
  15. REDHAT_SUPPORT_PRODUCT_VERSION="7"

帮助文档
image.png

  1. #1、卸载旧的版本
  2. yum remove docker \
  3. docker-client \
  4. docker-client-latest \
  5. docker-common \
  6. docker-latest \
  7. docker-latest-logrotate \
  8. docker-logrotate \
  9. docker-engine
  10. #2、需要的安装包
  11. yum install -y yum-utils
  12. #3、设置镜像的仓库
  13. yum-config-manager \
  14. --add-repo \
  15. https://download.docker.com/linux/centos/docker-ce.repo 默认是国外的仓库
  16. #阿里云
  17. yum-config-manager \
  18. --add-repo \
  19. http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  20. #更新yum
  21. yum makecache fast
  22. #4、安装docker-ce社区版
  23. yum install docker-ce docker-ce-cli containerd.io
  24. 5、启动docker
  25. systemctl start docker
  26. 6、测试helloworld
  27. docker run hello-world
  28. #使用docker version 查看docker安装成功

image.png

  1. 7、查看一下下载的hello-world镜像
  2. [root@localhost ~]# docker images
  3. REPOSITORY TAG IMAGE ID CREATED SIZE
  4. mysql latest 5c62e459e087 3 weeks ago 556MB
  5. hello-world latest d1165f221234 4 months ago 13.3kB

底层原理

Docker是怎么工作的?

Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!
DockerServer接收到Docker-Client的指令,就会执行这个指令。
image.png

Docker为什么比VM快?

1、Docker有着比虚拟机更少的抽象层。
2、Docker利用的是宿主机的内核,VM需要的是GuestOS。
image.png

所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导,虚拟机是加载Guest OS,分钟级别的,而Docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级!
image.png

帮助命令

  1. docker version #显示docker的版本信息
  2. docker info #显示docker的系统信息,包括镜像和容器的数量等
  3. docker 命令 --help #显示该命令的帮助命令

帮助文档的地址:https://docs.docker.com/engine/reference/commandline/dockerd/

镜像命令

docker images 查看所有本地的主机上的镜像

  1. [root@localhost ~]# docker images
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. mysql 5.7 9f1d21c1025a 4 days ago 448MB
  4. hello-world latest d1165f221234 4 months ago 13.3kB
  5. cptactionhank/atlassian-jira-software 8.1.0 f9f09151d8df 2 years ago 531MB
  6. #解释
  7. REPOSITORY 镜像的仓库
  8. TAG 镜像的版本
  9. IMAGE ID 镜像的唯一标识
  10. CREATED 镜像创建时间
  11. SIZE 镜像的大小
  12. #可选项
  13. [root@localhost ~]# docker images --help
  14. Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]
  15. List images
  16. Options:
  17. -a, --all #列出所有的镜像
  18. --digests Show digests
  19. -f, --filter filter Filter output based on conditions provided
  20. --format string Pretty-print images using a Go template
  21. --no-trunc Don't truncate output
  22. -q, --quiet #只显示镜像的ID

docker search 搜索镜像

  1. [root@localhost ~]# docker search mysql
  2. NAME DESCRIPTION STARS OFFICIAL AUTOMATED
  3. mysql MySQL is a widely used, open-source relation 11164 [OK]
  4. mariadb MariaDB Server is a high performing open sou 4235 [OK]
  5. #可选项 通过搜查来过滤
  6. --filter=STARS=5000 #搜索出来的镜像就是STARTS大于5000的
  7. --[root@localhost ~]# docker search --help
  8. Usage: docker search [OPTIONS] TERM
  9. Search the Docker Hub for images
  10. Options:
  11. -f, --filter filter Filter output based on conditions provided
  12. --format string Pretty-print search using a Go template
  13. --limit int Max number of search results (default 25)
  14. --no-trunc Don't truncate output
  15. [root@localhost ~]# docker search mysql --filter=STARS=5000
  16. NAME DESCRIPTION STARS OFFICIAL AUTOMATED
  17. mysql MySQL is a widely used, open-source relation… 11164 [OK]

docker pull 下载命令

  1. #下载镜像 docker pull 镜像名字[:tag]
  2. [root@localhost ~]# docker pull mysql
  3. Using default tag: latest #如果不写tag,默认就是latest最新版本
  4. latest: Pulling from library/mysql
  5. 33847f680f63: Pull complete #分层下载,docker image 的核心 联合文件系统
  6. 5cb67864e624: Pull complete
  7. 1a2b594783f5: Pull complete
  8. b30e406dd925: Pull complete
  9. 48901e306e4c: Pull complete
  10. 603d2b7147fd: Pull complete
  11. 802aa684c1c4: Pull complete
  12. 715d3c143a06: Pull complete
  13. 6978e1b7a511: Pull complete
  14. f0d78b0ac1be: Pull complete
  15. 35a94d251ed1: Pull complete
  16. 36f75719b1a9: Pull complete
  17. Digest: sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd #签名
  18. Status: Downloaded newer image for mysql:latest
  19. docker.io/library/mysql:latest #真实地址
  20. #两个命令等价
  21. docker pull mysql
  22. docker pull docker.io/library/mysql:latest
  23. #指定版本下载
  24. [root@localhost ~]# docker pull mysql:5.7
  25. 5.7: Pulling from library/mysql
  26. 33847f680f63: Already exists
  27. 5cb67864e624: Already exists
  28. 1a2b594783f5: Already exists
  29. b30e406dd925: Already exists
  30. 48901e306e4c: Already exists
  31. 603d2b7147fd: Already exists
  32. 802aa684c1c4: Already exists
  33. 5b5a19178915: Pull complete
  34. f9ce7411c6e4: Pull complete
  35. f51f6977d9b2: Pull complete
  36. aeb6b16ce012: Pull complete
  37. Digest: sha256:be70d18aedc37927293e7947c8de41ae6490ecd4c79df1db40d1b5b5af7d9596
  38. Status: Downloaded newer image for mysql:5.7
  39. docker.io/library/mysql:5.7
  40. #前面的内容可以看出是已经存在的文件,就不需要再次下载,只需更新新的内容,极大的节省内存,这就是联合文件系统

docker rmi 删除镜像

  1. [root@localhost ~]# docker rmi -f d1165f221234
  2. Untagged: hello-world:latest
  3. Untagged: hello-world@sha256:df5f5184104426b65967e016ff2ac0bfcd44ad7899ca3bbcf8e44e4461491a9e
  4. Deleted: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
  5. docker rmi -f 镜像ID #删除指定的镜像
  6. docker rmi -f 容器ID 容器ID 容器ID #删除多个镜像
  7. docker rmi -f $(docker images -aq) #删除全部的镜像

容器命令

我们有了镜像才可以创建容器,下载一个centos

  1. [root@localhost ~]# docker pull centos
  2. Using default tag: latest
  3. latest: Pulling from library/centos
  4. 7a0437f04f83: Pull complete
  5. Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
  6. Status: Downloaded newer image for centos:latest
  7. docker.io/library/centos:latest

新建容器并启动

  1. docker run [可选参数] image
  2. #参数说明
  3. --name="Name" 容器名字 tomcat01 tomcat02 ,用来区分容器
  4. -d 后台方式运行
  5. -it 使用交互方式运行,进入容器查看内容
  6. -p 指定容器的端口 -p 8080:8080
  7. -p ip:主机端口:容器端口
  8. -p 主机端口:容器端口(常用)
  9. -p 容器端口
  10. -P 随机指定端口
  11. #测试一下 启动并进入容器
  12. [root@localhost ~]# docker run -it centos /bin/bash
  13. [root@0f6efcd405d9 /]# ls #查看容器内的centos
  14. bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
  15. #从容器中退出到主机
  16. [root@0f6efcd405d9 /]# exit
  17. exit
  18. [root@localhost ~]# ls
  19. anaconda-ks.cfg jira-master.zip xampp-linux-x64-7.4.14-0-installer.run.1
  20. atlassian-jira-software-7.2.2-x64.bin xampp-linux-x64-7.4.14-0-installer.run

列出所有的运行的容器

  1. #docker ps 命令
  2. #列出当前正在运行的容器
  3. -a #列出当前正在运行的容器 + 带出历史运行的容器
  4. -n=? #显示最近创建的容器
  5. -q #只显示容器的编号
  6. [root@localhost ~]# docker ps
  7. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  8. [root@localhost ~]# docker ps -a
  9. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  10. 0f6efcd405d9 centos "/bin/bash" 4 minutes ago Exited (0) About a minute ago strange_grothendieck
  11. 1e87b2e797e1 cptactionhank/atlassian-jira-software:8.1.0 "/docker-entrypoint.…" 46 hours ago Exited (255) 59 minutes ago 0.0.0.0:8090->8080/tcp, :::8090->8080/tcp jira-software
  12. 1853c568ab06 9f1d21c1025a "docker-entrypoint.s…" 46 hours ago Exited (255) 59 minutes ago 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
  13. c5812bde1a92 d1165f221234 "/hello" 3 days ago Exited (0) 3 days ago vibrant_cartwright
  14. ba84d1187514 d1165f221234 "/hello" 5 days ago Exited (0) 5 days ago condescending_mahavira

退出容器

  1. exit #直接容器停止并退出
  2. Ctrl + P + Q #容器不停止退出
  3. [root@localhost ~]# docker ps #当前没有容器运行
  4. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  5. [root@localhost ~]# docker run -it centos /bin/bash #容器不停止退出
  6. [root@cd37c8887b62 /]# [root@localhost ~]# docker ps #可以看到当前正在运行的容器
  7. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  8. cd37c8887b62 centos "/bin/bash" 21 seconds ago Up 20 seconds clever_fermat

删除容器

  1. docker rm 容器ID #删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm-f
  2. docker rm -f $(docker ps -aq) #删除所有的容器
  3. docker ps -a -q|xargs docker rm #删除所有的容器
  4. [root@localhost ~]# docker rm cd37c8887b62
  5. Error response from daemon: You cannot remove a running container cd37c8887b6241953c518df86764812a24751d92853e759837e98b5153f2840e. Stop the container before attempting removal or force remove
  6. [root@localhost ~]# docker rm -f cd37c8887b62
  7. cd37c8887b62

启动和停止容器的操作

  1. docker start 容器ID #启动容器
  2. docker restart 容器ID #重启容器
  3. docker stop 容器ID #停止当前正在运行的容器
  4. docker kill 容器ID #强制停止当前容器

常用其他命令

后台启动容器

  1. #docker run -d 镜像名
  2. [root@localhost ~]# docker ps
  3. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  4. [root@localhost ~]# docker run -d centos
  5. 579465de4963353554e1bd2af04782c263223f674552c329b555336ad22083cc
  6. [root@localhost ~]# docker ps
  7. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  8. 从上面可以发现问题:在使用命令后台启动centos之后,docker ps 发现没有运行的容器
  9. centos停止运行了?
  10. 为什么?
  11. 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止

查看日志

  1. docker logs -f -t --taii 容器,发现容器没有日志
  2. #自己编写一段shell脚本
  3. [root@localhost ~]# docker run -d centos /bin/sh -c "while true;do echo hello,world;sleep 1;done"
  4. 94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f
  5. [root@localhost ~]# docker ps
  6. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  7. 94a80050dc4b centos "/bin/sh -c 'while t…" 29 seconds ago Up 28 seconds nervous_kare
  8. [root@localhost ~]# docker logs -tf --tail 10 94a80050dc4b
  9. 2021-07-24T09:45:35.957645789Z hello,world
  10. 2021-07-24T09:45:36.962548024Z hello,world
  11. 2021-07-24T09:45:37.967424222Z hello,world
  12. 2021-07-24T09:45:38.970952228Z hello,world
  13. #显示日志
  14. -tf #显示日志 t 显示时间戳
  15. --tail number #要显示的日志条数

查看容器中进程信息

  1. [root@localhost ~]# docker top 94a80050dc4b
  2. UID PID PPID C STIME TTY TIME CMD
  3. root 3914 3895 0 17:44 ? 00:00:00 /bin/sh -c while true;do echo hello,world;sleep 1;done
  4. root 4430 3914 0 17:50 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
  5. [root@localhost ~]#

查看容器中的元数据

  1. docker inspect 容器id
  2. [root@localhost ~]# docker inspect 94a80050dc4b
  3. [
  4. {
  5. "Id": "94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f", #可以看到这里 我们容器ID的就是这里容器id取了前几位
  6. "Created": "2021-07-24T09:44:30.154427774Z",
  7. "Path": "/bin/sh", #容器的启动路径
  8. "Args": [
  9. "-c",
  10. "while true;do echo hello,world;sleep 1;done" #刚刚那个手写的脚本 一直循环输入hello world 每一秒
  11. ],
  12. "State": {
  13. "Status": "running",
  14. "Running": true,
  15. "Paused": false,
  16. "Restarting": false,
  17. "OOMKilled": false,
  18. "Dead": false,
  19. "Pid": 3914,
  20. "ExitCode": 0,
  21. "Error": "",
  22. "StartedAt": "2021-07-24T09:44:30.626810771Z",
  23. "FinishedAt": "0001-01-01T00:00:00Z"
  24. },
  25. "Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
  26. "ResolvConfPath": "/var/lib/docker/containers/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f/resolv.conf",
  27. "HostnamePath": "/var/lib/docker/containers/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f/hostname",
  28. "HostsPath": "/var/lib/docker/containers/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f/hosts",
  29. "LogPath": "/var/lib/docker/containers/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f-json.log",
  30. "Name": "/nervous_kare",
  31. "RestartCount": 0,
  32. "Driver": "overlay2",
  33. "Platform": "linux",
  34. "MountLabel": "",
  35. "ProcessLabel": "",
  36. "AppArmorProfile": "",
  37. "ExecIDs": null,
  38. "HostConfig": {
  39. "Binds": null,
  40. "ContainerIDFile": "",
  41. "LogConfig": {
  42. "Type": "json-file",
  43. "Config": {
  44. "max-size": "100m"
  45. }
  46. },
  47. "NetworkMode": "default",
  48. "PortBindings": {},
  49. "RestartPolicy": {
  50. "Name": "no",
  51. "MaximumRetryCount": 0
  52. },
  53. "AutoRemove": false,
  54. "VolumeDriver": "",
  55. "VolumesFrom": null,
  56. "CapAdd": null,
  57. "CapDrop": null,
  58. "CgroupnsMode": "host",
  59. "Dns": [],
  60. "DnsOptions": [],
  61. "DnsSearch": [],
  62. "ExtraHosts": null,
  63. "GroupAdd": null,
  64. "IpcMode": "private",
  65. "Cgroup": "",
  66. "Links": null,
  67. "OomScoreAdj": 0,
  68. "PidMode": "",
  69. "Privileged": false,
  70. "PublishAllPorts": false,
  71. "ReadonlyRootfs": false,
  72. "SecurityOpt": null,
  73. "UTSMode": "",
  74. "UsernsMode": "",
  75. "ShmSize": 67108864,
  76. "Runtime": "runc",
  77. "ConsoleSize": [
  78. 0,
  79. 0
  80. ],
  81. "Isolation": "",
  82. "CpuShares": 0,
  83. "Memory": 0,
  84. "NanoCpus": 0,
  85. "CgroupParent": "",
  86. "BlkioWeight": 0,
  87. "BlkioWeightDevice": [],
  88. "BlkioDeviceReadBps": null,
  89. "BlkioDeviceWriteBps": null,
  90. "BlkioDeviceReadIOps": null,
  91. "BlkioDeviceWriteIOps": null,
  92. "CpuPeriod": 0,
  93. "CpuQuota": 0,
  94. "CpuRealtimePeriod": 0,
  95. "CpuRealtimeRuntime": 0,
  96. "CpusetCpus": "",
  97. "CpusetMems": "",
  98. "Devices": [],
  99. "DeviceCgroupRules": null,
  100. "DeviceRequests": null,
  101. "KernelMemory": 0,
  102. "KernelMemoryTCP": 0,
  103. "MemoryReservation": 0,
  104. "MemorySwap": 0,
  105. "MemorySwappiness": null,
  106. "OomKillDisable": false,
  107. "PidsLimit": null,
  108. "Ulimits": null,
  109. "CpuCount": 0,
  110. "CpuPercent": 0,
  111. "IOMaximumIOps": 0,
  112. "IOMaximumBandwidth": 0,
  113. "MaskedPaths": [
  114. "/proc/asound",
  115. "/proc/acpi",
  116. "/proc/kcore",
  117. "/proc/keys",
  118. "/proc/latency_stats",
  119. "/proc/timer_list",
  120. "/proc/timer_stats",
  121. "/proc/sched_debug",
  122. "/proc/scsi",
  123. "/sys/firmware"
  124. ],
  125. "ReadonlyPaths": [
  126. "/proc/bus",
  127. "/proc/fs",
  128. "/proc/irq",
  129. "/proc/sys",
  130. "/proc/sysrq-trigger"
  131. ]
  132. },
  133. "GraphDriver": {
  134. "Data": {
  135. "LowerDir": "/var/lib/docker/overlay2/dd4bfbc3d94f5ba7595ffec677271b7e7ea12ac16e8deadc9557737ced4155b4-init/diff:/var/lib/docker/overlay2/57444df837df39ca7b692f700d46e99c9ac472d0a79463398c5c1baffb11e9d0/diff",
  136. "MergedDir": "/var/lib/docker/overlay2/dd4bfbc3d94f5ba7595ffec677271b7e7ea12ac16e8deadc9557737ced4155b4/merged",
  137. "UpperDir": "/var/lib/docker/overlay2/dd4bfbc3d94f5ba7595ffec677271b7e7ea12ac16e8deadc9557737ced4155b4/diff",
  138. "WorkDir": "/var/lib/docker/overlay2/dd4bfbc3d94f5ba7595ffec677271b7e7ea12ac16e8deadc9557737ced4155b4/work"
  139. },
  140. "Name": "overlay2"
  141. },
  142. "Mounts": [],
  143. "Config": {
  144. "Hostname": "94a80050dc4b",
  145. "Domainname": "",
  146. "User": "",
  147. "AttachStdin": false,
  148. "AttachStdout": false,
  149. "AttachStderr": false,
  150. "Tty": false,
  151. "OpenStdin": false,
  152. "StdinOnce": false,
  153. "Env": [
  154. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  155. ],
  156. "Cmd": [
  157. "/bin/sh",
  158. "-c",
  159. "while true;do echo hello,world;sleep 1;done"
  160. ],
  161. "Image": "centos",
  162. "Volumes": null,
  163. "WorkingDir": "",
  164. "Entrypoint": null,
  165. "OnBuild": null,
  166. "Labels": {
  167. "org.label-schema.build-date": "20201204",
  168. "org.label-schema.license": "GPLv2",
  169. "org.label-schema.name": "CentOS Base Image",
  170. "org.label-schema.schema-version": "1.0",
  171. "org.label-schema.vendor": "CentOS"
  172. }
  173. },
  174. "NetworkSettings": {
  175. "Bridge": "",
  176. "SandboxID": "9e0b6936f4fa99b01c7803e6fa505807eec0ade1bdf48ef929e68dd1e365eb09",
  177. "HairpinMode": false,
  178. "LinkLocalIPv6Address": "",
  179. "LinkLocalIPv6PrefixLen": 0,
  180. "Ports": {},
  181. "SandboxKey": "/var/run/docker/netns/9e0b6936f4fa",
  182. "SecondaryIPAddresses": null,
  183. "SecondaryIPv6Addresses": null,
  184. "EndpointID": "4e44f3eaad9d60a39b1885d26a6b7d7bb2ffd906bbde6aff3c083e7f80065482",
  185. "Gateway": "172.17.0.1",
  186. "GlobalIPv6Address": "",
  187. "GlobalIPv6PrefixLen": 0,
  188. "IPAddress": "172.17.0.3",
  189. "IPPrefixLen": 16,
  190. "IPv6Gateway": "",
  191. "MacAddress": "02:42:ac:11:00:03",
  192. "Networks": {
  193. "bridge": {
  194. "IPAMConfig": null,
  195. "Links": null,
  196. "Aliases": null,
  197. "NetworkID": "517171546df0fe9e01080f2fdfd4183ebcaba019655f8cec73ef220eb2b39eaa",
  198. "EndpointID": "4e44f3eaad9d60a39b1885d26a6b7d7bb2ffd906bbde6aff3c083e7f80065482",
  199. "Gateway": "172.17.0.1",
  200. "IPAddress": "172.17.0.3",
  201. "IPPrefixLen": 16,
  202. "IPv6Gateway": "",
  203. "GlobalIPv6Address": "",
  204. "GlobalIPv6PrefixLen": 0,
  205. "MacAddress": "02:42:ac:11:00:03",
  206. "DriverOpts": null
  207. }
  208. }
  209. }
  210. }
  211. ]

进入当前正在运行的容器

  1. #我们通常容器都是使用后台方式运行的,需要进入容器修改一些配置时
  2. #命令
  3. docker exec -it 容器id BashShell
  4. #测试
  5. [root@localhost ~]# docker ps
  6. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  7. 51fa8fe0d85b centos "/bin/bash" 20 seconds ago Up 19 seconds quirky_elion
  8. [root@localhost ~]# docker exec -it 51fa8fe0d85b /bin/bash
  9. [root@51fa8fe0d85b /]# ls
  10. bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
  11. [root@51fa8fe0d85b /]# ps -ef
  12. UID PID PPID C STIME TTY TIME CMD
  13. root 1 0 0 09:14 pts/0 00:00:00 /bin/bash
  14. root 15 0 0 09:15 pts/1 00:00:00 /bin/bash
  15. root 32 15 0 09:16 pts/1 00:00:00 ps -ef
  16. #方式二
  17. docker attach 容器id
  18. [root@localhost ~]# docker attach 51fa8fe0d85b
  19. #docker exec #进入容器后开启一个新的终端
  20. #docker attach #进入容器正在执行的终端,不会启动新的进程!

从容器内拷贝文件到主机上

  1. docker cp 容器id
  2. [root@localhost home]# docker attach 2075c5dd8b33 #进入docker容器内部
  3. [root@2075c5dd8b33 /]# cd /home
  4. [root@2075c5dd8b33 home]# ls
  5. #在容器内新建一个文件
  6. [root@2075c5dd8b33 home]# touch test.java
  7. [root@2075c5dd8b33 home]# exit
  8. exit
  9. #将文件拷贝出来到主机上
  10. [root@localhost home]# docker cp 2075c5dd8b33:/home/test.java /home
  11. [root@localhost home]# ls
  12. hello.java jira test.java
  13. #拷贝是一个手动过程,未来使用-v 卷的技术,可以实现,自动同步

作业练习

作业:Docker安装Nginx

  1. #1、搜索镜像
  2. #2、下载镜像 pull
  3. #3、运行测试
  4. [root@localhost home]# docker pull nginx
  5. Using default tag: latest
  6. latest: Pulling from library/nginx
  7. 33847f680f63: Already exists
  8. dbb907d5159d: Pull complete
  9. 8a268f30c42a: Pull complete
  10. b10cf527a02d: Pull complete
  11. c90b090c213b: Pull complete
  12. 1f41b2f2bf94: Pull complete
  13. Digest: sha256:8f335768880da6baf72b70c701002b45f4932acae8d574dedfddaf967fc3ac90
  14. Status: Downloaded newer image for nginx:latest
  15. docker.io/library/nginx:latest
  16. #-d 后台运行
  17. #--name 给容器命名
  18. #-p 暴露端口 宿主机端口:容器内部端口
  19. [root@localhost home]# docker run -d --name nginx01 -p 3344:80 nginx
  20. 3960a4e43a0252633d1b61f16902bd3926b43111e390b0d812a4daa0544656ac
  21. [root@localhost home]# docker ps
  22. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  23. 3960a4e43a02 nginx "/docker-entrypoint.…" 15 seconds ago Up 14 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
  24. [root@localhost home]# curl localhost:3344
  25. <!DOCTYPE html>
  26. <html>
  27. <head>
  28. <title>Welcome to nginx!</title>
  29. <style>
  30. body {
  31. width: 35em;
  32. margin: 0 auto;
  33. font-family: Tahoma, Verdana, Arial, sans-serif;
  34. }
  35. </style>
  36. </head>
  37. <body>
  38. <h1>Welcome to nginx!</h1>
  39. <p>If you see this page, the nginx web server is successfully installed and
  40. working. Further configuration is required.</p>
  41. <p>For online documentation and support please refer to
  42. <a href="http://nginx.org/">nginx.org</a>.<br/>
  43. Commercial support is available at
  44. <a href="http://nginx.com/">nginx.com</a>.</p>
  45. <p><em>Thank you for using nginx.</em></p>
  46. </body>
  47. </html>
  48. #进入Nginx容器
  49. [root@localhost home]# docker ps
  50. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  51. 3960a4e43a02 nginx "/docker-entrypoint.…" 9 minutes ago Up 9 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
  52. [root@localhost home]# docker exec -it nginx01 /bin/bash
  53. root@3960a4e43a02:/# whereis nginx
  54. nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
  55. root@3960a4e43a02:/# cd /etc/nginx/
  56. root@3960a4e43a02:/etc/nginx# ls
  57. conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
  58. root@3960a4e43a02:/etc/nginx#

image.png
image.png
思考问题:我们每次改动Nginx配置文件,都需要进入容器内部,很麻烦,我要是可以在容器外部提供一个映射路径,达到在容器外部修改文件,容器内部就可以自动修改?? -v 数据卷技术!

作业:部署Tomcat

  1. #官方的使用 run -it --rm tomcat:9.0
  2. docker run -it --rm tomcat:9.0
  3. #我们之前的启动都是后天启动,停止了容器之后,容器还是可以查到,docker run -it --rm 一般用来测试,用完就删除
  4. #下载启动
  5. docker pull tomcat
  6. #启动运行
  7. docker run -d -p 3355:8080 --name tomcat01 tomcat
  8. #用完就删除的方式测试
  9. [root@localhost home]# docker run -it --rm tomcat:9.0
  10. Unable to find image 'tomcat:9.0' locally
  11. 9.0: Pulling from library/tomcat
  12. 627b765e08d1: Pull complete
  13. c040670e5e55: Pull complete
  14. 073a180f4992: Pull complete
  15. bf76209566d0: Pull complete
  16. f10db7ba7580: Pull complete
  17. 5b2f970878fa: Pull complete
  18. ed434bfebf18: Pull complete
  19. f6c437110aa9: Pull complete
  20. a772951f83db: Pull complete
  21. 752225c3768e: Pull complete
  22. Digest: sha256:6e40250d8fac4eca05c2067cb81f79427e4ddbaf4e78d5ecd21c35e8c5f2bfcf
  23. Status: Downloaded newer image for tomcat:9.0
  24. Using CATALINA_BASE: /usr/local/tomcat
  25. Using CATALINA_HOME: /usr/local/tomcat
  26. Using CATALINA_TMPDIR: /usr/local/tomcat/temp
  27. Using JRE_HOME: /usr/local/openjdk-11
  28. Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
  29. Using CATALINA_OPTS:
  30. #启动运行
  31. [root@localhost home]# docker run -d -p 3355:8080 --name tomcat01 tomcat:9.0
  32. 48e19c70ce022167ea3c69bdbe61195a622f858f63985af01335ddfe1dbc0de4
  33. [root@localhost home]# docker exec -it tomcat01 /bin/bash
  34. root@48e19c70ce02:/usr/local/tomcat# ll
  35. bash: ll: command not found
  36. #发现问题:1、Linux命令少了 2、webapps中没有部署应用。 由于镜像的原因这里的命令是缺少的,默认镜像要保证最小可运行环境的安装,所以有些东西是被剔除掉了
  37. root@48e19c70ce02:/usr/local/tomcat# ls
  38. BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist
  39. CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work
  40. root@48e19c70ce02:/usr/local/tomcat# cd webapps
  41. root@48e19c70ce02:/usr/local/tomcat/webapps# ls
  42. #这个webapps下面是没有部署任何应用的
  43. root@48e19c70ce02:/usr/local/tomcat/webapps# cd ..
  44. root@48e19c70ce02:/usr/local/tomcat# cd webapps.dist/
  45. root@48e19c70ce02:/usr/local/tomcat/webapps.dist# ls
  46. ROOT docs examples host-manager manager
  47. root@48e19c70ce02:/usr/local/tomcat/webapps.dist# cd ..
  48. root@48e19c70ce02:/usr/local/tomcat# cp -r webapps.dist/* webapps #将webapps.dist文件下的拷贝到webapps部署应用
  49. root@48e19c70ce02:/usr/local/tomcat# cd webapps
  50. root@48e19c70ce02:/usr/local/tomcat/webapps# ls
  51. ROOT docs examples host-manager manager
  52. #这里就部署好了tomcat 映射端口号是3355

image.png
思考问题:以后如果需要用docker部署tomcat,然后需要在tomcat上部署我们自己的应用,就需要进入容器,非常的麻烦。
所以还是那个问题。可以在容器外部提供一个映射路径,webapps,我们在外部部署项目,就自动同步到内部就好了!

作业:部署es+kibana

  1. #es 暴露的端口很多!
  2. #es 十分的耗内存
  3. #es 的数据一般需要放置到安全目录!挂载
  4. #docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag
  5. # --net somenetwork ? docker网络配置
  6. #启动elasticsearch
  7. docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
  8. [root@localhost ~]# curl localhost:9200
  9. {
  10. "name" : "8da72f00f4a3",
  11. "cluster_name" : "docker-cluster",
  12. "cluster_uuid" : "8cTmM07VR8ezLtoZUQUw9g",
  13. "version" : {
  14. "number" : "7.6.2",
  15. "build_flavor" : "default",
  16. "build_type" : "docker",
  17. "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
  18. "build_date" : "2020-03-26T06:34:37.794943Z",
  19. "build_snapshot" : false,
  20. "lucene_version" : "8.4.0",
  21. "minimum_wire_compatibility_version" : "6.8.0",
  22. "minimum_index_compatibility_version" : "6.0.0-beta1"
  23. },
  24. "tagline" : "You Know, for Search"
  25. }
  26. #此时仅仅es就占用了1.2个G的内存
  27. #使用docker stats 来查看内存 以及cpu的状态
  28. #赶紧关闭,增加内存的限制,修改配置文件 -e 环境配置修改 最小内存64m 最大内存512m
  29. docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node"
  30. -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
  31. CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
  32. 68fd7232219b elasticsearch02 0.44% 392MiB / 3.685GiB 10.39% 648B / 0B 0B / 696kB 47
  33. ^C
  34. [root@localhost ~]# curl localhost:9200
  35. {
  36. "name" : "68fd7232219b",
  37. "cluster_name" : "docker-cluster",
  38. "cluster_uuid" : "P9WkyzOdT564mq2b0_sdAQ",
  39. "version" : {
  40. "number" : "7.6.2",
  41. "build_flavor" : "default",
  42. "build_type" : "docker",
  43. "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
  44. "build_date" : "2020-03-26T06:34:37.794943Z",
  45. "build_snapshot" : false,
  46. "lucene_version" : "8.4.0",
  47. "minimum_wire_compatibility_version" : "6.8.0",
  48. "minimum_index_compatibility_version" : "6.0.0-beta1"
  49. },
  50. "tagline" : "You Know, for Search"
  51. }

image.png
image.png

作业:使用kibana连接es 思考网络如何才能连过去!
image.png

可视化

  • portainer (先用这个)

    1. docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  • Rancher (CI/CD再用)

什么是portainer?

docker图形化界面管理工具!提供一个后台面板供我们操作!

  1. [root@localhost ~]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  2. Unable to find image 'portainer/portainer:latest' locally
  3. latest: Pulling from portainer/portainer
  4. 94cfa856b2b1: Pull complete
  5. 49d59ee0881a: Pull complete
  6. a2300fd28637: Pull complete
  7. Digest: sha256:fb45b43738646048a0a0cc74fcee2865b69efde857e710126084ee5de9be0f3f
  8. Status: Downloaded newer image for portainer/portainer:latest
  9. 6fd8a8735359499d8d0bc0990fd636a963653242fd781055a2c3ec6adb1e1ae2

访问外网测试:ip:192.168.150.131:8088
image.png
进入之后选择本地
image.png

镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包docker镜像,就可以直接跑起来!
如何得到镜像:

  • 从远程仓库下载
  • 朋友拷贝给你
  • 自己制作一个镜像DockerFile

    Docker镜像加载原理

    UnionFS联合文件系统

    UnionFS联合文件系统:是一种分层、轻量级并且高效能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。联合文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
    不同的Docker容器可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终文件系统会包含所有底层的文件和目录。

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader 和kernel,BootLoader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含BootLoader和内核,当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs(root file system),在bootfs之上,包含的就是典型Linux系统中的/dev, /proc, /bin, /etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,CentOS。
image.png

平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用的host的kernel,自己只需要提供一个rootfs就可以了。由此可见对于不同的Linux发行版,bootfs是基本一致的,rootfs会有差距,因此不同的发行版可以直接公用bootfs。

分层理解

思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处,就是资源共享。比如说有多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了。而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过docker image inspect命令

  1. [root@localhost ~]# docker image inspect redis:latest
  2. "Layers": [
  3. "sha256:814bff7343242acfd20a2c841e041dd57c50f0cf844d4abd2329f78b992197f4",
  4. "sha256:dd1ebb1f5319785e34838c7332a71e5255bda9ccf61d2a0bf3bff3d2c3f4cdb4",
  5. "sha256:11f99184504048b93dc2bdabf1999d6bc7d9d9ded54d15a5f09e36d8c571c32d",
  6. "sha256:e461360755916af80821289b1cbc503692cf63e4e93f09b35784d9f7a819f7f2",
  7. "sha256:45f6df6342536d948b07e9df6ad231bf17a73e5861a84fc3c9ee8a59f73d0f9f",
  8. "sha256:262de04acb7e0165281132c876c0636c358963aa3e0b99e7fbeb8aba08c06935"
  9. ]

理解:
所有的Docker镜像都起始于一个基础镜像层,当进行修改或者增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu创建一个新的镜像,这就是新镜像的第一层,如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层,如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含了3个镜像层,如图所示:
image.png

上图中的镜像层跟之前途中的略有区别,主要目的是便于展示文件。
下图中展示了稍微复杂的三层镜像,在外部看来整个镜像只有六个文件,这是因为最上层的文件7是文件5的一个更新版本
image.png
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像中。
Docker通过存储引擎(新版本采用快照机制)的方式实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、OVERLAY2、DEVICE MAPPER等,顾名思义,每种存储引擎都是基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都具有独有的性能特点。

特点:Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层就是容器层,容器之下位镜像层。你的所有操作都是基于容器层的。

commit镜像

如何提交一个自己的镜像

  1. docker commit 提交容器成为一个新的副本
  2. #命令和git原理类似
  3. docker commit -m="提交的描述信息" -a="作者" 容器ID 目标镜像名:[TAG] 镜像名不可以有大写字母
  4. [root@localhost ~]# docker commit -m="ADD WEBAPPS APP" -a="guohaibo" 4d00846e722e tomcatweb:1.0
  5. sha256:40dba6e2662f8945e1d4296dceb6b53ff87bde37e29ccb8e729715073ca5cf16

到了这里才算入门docker ,容器数据卷、dockerFile 、Docker网络才是核心要学的东西。

三体中的一句话:弱小和无知不是生存的障碍,傲慢才是!