Docker为什么出现?
一款产品:开发—上线两套环境!应用环境,应用配置
开发 —— 运维 。问题:我在我的电脑上可以运行!版本更新,导致服务不可用,对于运维来说,考验十分大。
环境配置是非常麻烦的,每一个机器都要配置环境,费时费力。
发布一个项目,能不能都带上环境安装打包?
Docker给以上问题,提出了解决办法。
Docker的思想就来自于集装箱!
隔离是Docker核心思想,打包装箱,每个箱子都是互相隔离的。
Docker通过隔离机制,可以将服务器利用到机制。
Docker能干吗?
之前的虚拟机技术:

虚拟机技术缺点:
1、资源占用十分多
2、冗余步骤多
3、启动慢
容器化技术:
容器化技术不是模拟一个完整的操作系统
比较Docker和虚拟机技术的不同:
传统虚拟机:虚拟出一套硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟硬件,
每个容器是互相隔离的,每个容器内都有一个属于自己的文件系统,互不影响。
DevOps
应用更快速的交付和部署
传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行
更便捷的升级和扩缩容
使用了Docker之后,我们部署应用就和搭积木一样!项目打包为一个镜像,当在服务器A上性能出现瓶颈了,我们要扩展到服务器B上,做负载均衡,直接水平扩展到服务器B上一键运行。
更简单的系统运维
在容器化之后,我们的开发测试环境都是高度一致的。
更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上运行很多个容器实例,服务器的性能被压榨到极致。
Docker的基本组成

镜像(image):docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,例如通过tomcat镜像创建出tomcat01容器,这个容器提供服务器。
容器(container):Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建。启动停止删除还有基本命令。
目前就可以吧这个容器理解为一个建议的Linux系统
仓库(repository):
仓库就是存放镜像的地方
安装Docker
环境准备
1、Linux基础
2、CentOS 7
3、使用Xshell连接远程服务器进行操作!
环境查看
系统内核是3.10以上[root@localhost ~]# uname -r3.10.0-862.el7.x86_64
系统版本
[root@localhost ~]# cat /etc/os-releaseNAME="CentOS Linux"VERSION="7 (Core)"ID="centos"ID_LIKE="rhel fedora"VERSION_ID="7"PRETTY_NAME="CentOS Linux 7 (Core)"ANSI_COLOR="0;31"CPE_NAME="cpe:/o:centos:centos:7"HOME_URL="https://www.centos.org/"BUG_REPORT_URL="https://bugs.centos.org/"CENTOS_MANTISBT_PROJECT="CentOS-7"CENTOS_MANTISBT_PROJECT_VERSION="7"REDHAT_SUPPORT_PRODUCT="centos"REDHAT_SUPPORT_PRODUCT_VERSION="7"
帮助文档
#1、卸载旧的版本yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine#2、需要的安装包yum install -y yum-utils#3、设置镜像的仓库yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo 默认是国外的仓库#阿里云yum-config-manager \--add-repo \http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo#更新yumyum makecache fast#4、安装docker-ce社区版yum install docker-ce docker-ce-cli containerd.io5、启动dockersystemctl start docker6、测试helloworlddocker run hello-world#使用docker version 查看docker安装成功

7、查看一下下载的hello-world镜像[root@localhost ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEmysql latest 5c62e459e087 3 weeks ago 556MBhello-world latest d1165f221234 4 months ago 13.3kB
底层原理
Docker是怎么工作的?
Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!
DockerServer接收到Docker-Client的指令,就会执行这个指令。
Docker为什么比VM快?
1、Docker有着比虚拟机更少的抽象层。
2、Docker利用的是宿主机的内核,VM需要的是GuestOS。
所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导,虚拟机是加载Guest OS,分钟级别的,而Docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级!
帮助命令
docker version #显示docker的版本信息docker info #显示docker的系统信息,包括镜像和容器的数量等docker 命令 --help #显示该命令的帮助命令
帮助文档的地址:https://docs.docker.com/engine/reference/commandline/dockerd/
镜像命令
docker images 查看所有本地的主机上的镜像
[root@localhost ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEmysql 5.7 9f1d21c1025a 4 days ago 448MBhello-world latest d1165f221234 4 months ago 13.3kBcptactionhank/atlassian-jira-software 8.1.0 f9f09151d8df 2 years ago 531MB#解释REPOSITORY 镜像的仓库TAG 镜像的版本IMAGE ID 镜像的唯一标识CREATED 镜像创建时间SIZE 镜像的大小#可选项[root@localhost ~]# docker images --helpUsage: docker images [OPTIONS] [REPOSITORY[:TAG]]List imagesOptions:-a, --all #列出所有的镜像--digests Show digests-f, --filter filter Filter output based on conditions provided--format string Pretty-print images using a Go template--no-trunc Don't truncate output-q, --quiet #只显示镜像的ID
docker search 搜索镜像
[root@localhost ~]# docker search mysqlNAME DESCRIPTION STARS OFFICIAL AUTOMATEDmysql MySQL is a widely used, open-source relation… 11164 [OK]mariadb MariaDB Server is a high performing open sou… 4235 [OK]#可选项 通过搜查来过滤--filter=STARS=5000 #搜索出来的镜像就是STARTS大于5000的--[root@localhost ~]# docker search --helpUsage: docker search [OPTIONS] TERMSearch the Docker Hub for imagesOptions:-f, --filter filter Filter output based on conditions provided--format string Pretty-print search using a Go template--limit int Max number of search results (default 25)--no-trunc Don't truncate output[root@localhost ~]# docker search mysql --filter=STARS=5000NAME DESCRIPTION STARS OFFICIAL AUTOMATEDmysql MySQL is a widely used, open-source relation… 11164 [OK]
docker pull 下载命令
#下载镜像 docker pull 镜像名字[:tag][root@localhost ~]# docker pull mysqlUsing default tag: latest #如果不写tag,默认就是latest最新版本latest: Pulling from library/mysql33847f680f63: Pull complete #分层下载,docker image 的核心 联合文件系统5cb67864e624: Pull complete1a2b594783f5: Pull completeb30e406dd925: Pull complete48901e306e4c: Pull complete603d2b7147fd: Pull complete802aa684c1c4: Pull complete715d3c143a06: Pull complete6978e1b7a511: Pull completef0d78b0ac1be: Pull complete35a94d251ed1: Pull complete36f75719b1a9: Pull completeDigest: sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd #签名Status: Downloaded newer image for mysql:latestdocker.io/library/mysql:latest #真实地址#两个命令等价docker pull mysqldocker pull docker.io/library/mysql:latest#指定版本下载[root@localhost ~]# docker pull mysql:5.75.7: Pulling from library/mysql33847f680f63: Already exists5cb67864e624: Already exists1a2b594783f5: Already existsb30e406dd925: Already exists48901e306e4c: Already exists603d2b7147fd: Already exists802aa684c1c4: Already exists5b5a19178915: Pull completef9ce7411c6e4: Pull completef51f6977d9b2: Pull completeaeb6b16ce012: Pull completeDigest: sha256:be70d18aedc37927293e7947c8de41ae6490ecd4c79df1db40d1b5b5af7d9596Status: Downloaded newer image for mysql:5.7docker.io/library/mysql:5.7#前面的内容可以看出是已经存在的文件,就不需要再次下载,只需更新新的内容,极大的节省内存,这就是联合文件系统
docker rmi 删除镜像
[root@localhost ~]# docker rmi -f d1165f221234Untagged: hello-world:latestUntagged: hello-world@sha256:df5f5184104426b65967e016ff2ac0bfcd44ad7899ca3bbcf8e44e4461491a9eDeleted: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726docker rmi -f 镜像ID #删除指定的镜像docker rmi -f 容器ID 容器ID 容器ID #删除多个镜像docker rmi -f $(docker images -aq) #删除全部的镜像
容器命令
我们有了镜像才可以创建容器,下载一个centos
[root@localhost ~]# docker pull centosUsing default tag: latestlatest: Pulling from library/centos7a0437f04f83: Pull completeDigest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1Status: Downloaded newer image for centos:latestdocker.io/library/centos:latest
新建容器并启动
docker run [可选参数] image#参数说明--name="Name" 容器名字 tomcat01 tomcat02 ,用来区分容器-d 后台方式运行-it 使用交互方式运行,进入容器查看内容-p 指定容器的端口 -p 8080:8080-p ip:主机端口:容器端口-p 主机端口:容器端口(常用)-p 容器端口-P 随机指定端口#测试一下 启动并进入容器[root@localhost ~]# docker run -it centos /bin/bash[root@0f6efcd405d9 /]# ls #查看容器内的centosbin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var#从容器中退出到主机[root@0f6efcd405d9 /]# exitexit[root@localhost ~]# lsanaconda-ks.cfg jira-master.zip xampp-linux-x64-7.4.14-0-installer.run.1atlassian-jira-software-7.2.2-x64.bin xampp-linux-x64-7.4.14-0-installer.run
列出所有的运行的容器
#docker ps 命令#列出当前正在运行的容器-a #列出当前正在运行的容器 + 带出历史运行的容器-n=? #显示最近创建的容器-q #只显示容器的编号[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES[root@localhost ~]# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES0f6efcd405d9 centos "/bin/bash" 4 minutes ago Exited (0) About a minute ago strange_grothendieck1e87b2e797e1 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-software1853c568ab06 9f1d21c1025a "docker-entrypoint.s…" 46 hours ago Exited (255) 59 minutes ago 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysqlc5812bde1a92 d1165f221234 "/hello" 3 days ago Exited (0) 3 days ago vibrant_cartwrightba84d1187514 d1165f221234 "/hello" 5 days ago Exited (0) 5 days ago condescending_mahavira
退出容器
exit #直接容器停止并退出Ctrl + P + Q #容器不停止退出[root@localhost ~]# docker ps #当前没有容器运行CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES[root@localhost ~]# docker run -it centos /bin/bash #容器不停止退出[root@cd37c8887b62 /]# [root@localhost ~]# docker ps #可以看到当前正在运行的容器CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMEScd37c8887b62 centos "/bin/bash" 21 seconds ago Up 20 seconds clever_fermat
删除容器
docker rm 容器ID #删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm-fdocker rm -f $(docker ps -aq) #删除所有的容器docker ps -a -q|xargs docker rm #删除所有的容器[root@localhost ~]# docker rm cd37c8887b62Error response from daemon: You cannot remove a running container cd37c8887b6241953c518df86764812a24751d92853e759837e98b5153f2840e. Stop the container before attempting removal or force remove[root@localhost ~]# docker rm -f cd37c8887b62cd37c8887b62
启动和停止容器的操作
docker start 容器ID #启动容器docker restart 容器ID #重启容器docker stop 容器ID #停止当前正在运行的容器docker kill 容器ID #强制停止当前容器
常用其他命令
后台启动容器
#docker run -d 镜像名[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES[root@localhost ~]# docker run -d centos579465de4963353554e1bd2af04782c263223f674552c329b555336ad22083cc[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES从上面可以发现问题:在使用命令后台启动centos之后,docker ps 发现没有运行的容器centos停止运行了?为什么?常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
查看日志
docker logs -f -t --taii 容器,发现容器没有日志#自己编写一段shell脚本[root@localhost ~]# docker run -d centos /bin/sh -c "while true;do echo hello,world;sleep 1;done"94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES94a80050dc4b centos "/bin/sh -c 'while t…" 29 seconds ago Up 28 seconds nervous_kare[root@localhost ~]# docker logs -tf --tail 10 94a80050dc4b2021-07-24T09:45:35.957645789Z hello,world2021-07-24T09:45:36.962548024Z hello,world2021-07-24T09:45:37.967424222Z hello,world2021-07-24T09:45:38.970952228Z hello,world#显示日志-tf #显示日志 t 显示时间戳--tail number #要显示的日志条数
查看容器中进程信息
[root@localhost ~]# docker top 94a80050dc4bUID PID PPID C STIME TTY TIME CMDroot 3914 3895 0 17:44 ? 00:00:00 /bin/sh -c while true;do echo hello,world;sleep 1;doneroot 4430 3914 0 17:50 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1[root@localhost ~]#
查看容器中的元数据
docker inspect 容器id[root@localhost ~]# docker inspect 94a80050dc4b[{"Id": "94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f", #可以看到这里 我们容器ID的就是这里容器id取了前几位"Created": "2021-07-24T09:44:30.154427774Z","Path": "/bin/sh", #容器的启动路径"Args": ["-c","while true;do echo hello,world;sleep 1;done" #刚刚那个手写的脚本 一直循环输入hello world 每一秒],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 3914,"ExitCode": 0,"Error": "","StartedAt": "2021-07-24T09:44:30.626810771Z","FinishedAt": "0001-01-01T00:00:00Z"},"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55","ResolvConfPath": "/var/lib/docker/containers/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f/resolv.conf","HostnamePath": "/var/lib/docker/containers/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f/hostname","HostsPath": "/var/lib/docker/containers/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f/hosts","LogPath": "/var/lib/docker/containers/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f/94a80050dc4b064efc64a1f01b1b646e6e778b9afd7de8439f29e8102e3bec9f-json.log","Name": "/nervous_kare","RestartCount": 0,"Driver": "overlay2","Platform": "linux","MountLabel": "","ProcessLabel": "","AppArmorProfile": "","ExecIDs": null,"HostConfig": {"Binds": null,"ContainerIDFile": "","LogConfig": {"Type": "json-file","Config": {"max-size": "100m"}},"NetworkMode": "default","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0},"AutoRemove": false,"VolumeDriver": "","VolumesFrom": null,"CapAdd": null,"CapDrop": null,"CgroupnsMode": "host","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": "/var/lib/docker/overlay2/dd4bfbc3d94f5ba7595ffec677271b7e7ea12ac16e8deadc9557737ced4155b4-init/diff:/var/lib/docker/overlay2/57444df837df39ca7b692f700d46e99c9ac472d0a79463398c5c1baffb11e9d0/diff","MergedDir": "/var/lib/docker/overlay2/dd4bfbc3d94f5ba7595ffec677271b7e7ea12ac16e8deadc9557737ced4155b4/merged","UpperDir": "/var/lib/docker/overlay2/dd4bfbc3d94f5ba7595ffec677271b7e7ea12ac16e8deadc9557737ced4155b4/diff","WorkDir": "/var/lib/docker/overlay2/dd4bfbc3d94f5ba7595ffec677271b7e7ea12ac16e8deadc9557737ced4155b4/work"},"Name": "overlay2"},"Mounts": [],"Config": {"Hostname": "94a80050dc4b","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"Tty": false,"OpenStdin": false,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd": ["/bin/sh","-c","while true;do echo hello,world;sleep 1;done"],"Image": "centos","Volumes": null,"WorkingDir": "","Entrypoint": null,"OnBuild": null,"Labels": {"org.label-schema.build-date": "20201204","org.label-schema.license": "GPLv2","org.label-schema.name": "CentOS Base Image","org.label-schema.schema-version": "1.0","org.label-schema.vendor": "CentOS"}},"NetworkSettings": {"Bridge": "","SandboxID": "9e0b6936f4fa99b01c7803e6fa505807eec0ade1bdf48ef929e68dd1e365eb09","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {},"SandboxKey": "/var/run/docker/netns/9e0b6936f4fa","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "4e44f3eaad9d60a39b1885d26a6b7d7bb2ffd906bbde6aff3c083e7f80065482","Gateway": "172.17.0.1","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"IPAddress": "172.17.0.3","IPPrefixLen": 16,"IPv6Gateway": "","MacAddress": "02:42:ac:11:00:03","Networks": {"bridge": {"IPAMConfig": null,"Links": null,"Aliases": null,"NetworkID": "517171546df0fe9e01080f2fdfd4183ebcaba019655f8cec73ef220eb2b39eaa","EndpointID": "4e44f3eaad9d60a39b1885d26a6b7d7bb2ffd906bbde6aff3c083e7f80065482","Gateway": "172.17.0.1","IPAddress": "172.17.0.3","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:11:00:03","DriverOpts": null}}}}]
进入当前正在运行的容器
#我们通常容器都是使用后台方式运行的,需要进入容器修改一些配置时#命令docker exec -it 容器id BashShell#测试[root@localhost ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES51fa8fe0d85b centos "/bin/bash" 20 seconds ago Up 19 seconds quirky_elion[root@localhost ~]# docker exec -it 51fa8fe0d85b /bin/bash[root@51fa8fe0d85b /]# lsbin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var[root@51fa8fe0d85b /]# ps -efUID PID PPID C STIME TTY TIME CMDroot 1 0 0 09:14 pts/0 00:00:00 /bin/bashroot 15 0 0 09:15 pts/1 00:00:00 /bin/bashroot 32 15 0 09:16 pts/1 00:00:00 ps -ef#方式二docker attach 容器id[root@localhost ~]# docker attach 51fa8fe0d85b#docker exec #进入容器后开启一个新的终端#docker attach #进入容器正在执行的终端,不会启动新的进程!
从容器内拷贝文件到主机上
docker cp 容器id[root@localhost home]# docker attach 2075c5dd8b33 #进入docker容器内部[root@2075c5dd8b33 /]# cd /home[root@2075c5dd8b33 home]# ls#在容器内新建一个文件[root@2075c5dd8b33 home]# touch test.java[root@2075c5dd8b33 home]# exitexit#将文件拷贝出来到主机上[root@localhost home]# docker cp 2075c5dd8b33:/home/test.java /home[root@localhost home]# lshello.java jira test.java#拷贝是一个手动过程,未来使用-v 卷的技术,可以实现,自动同步
作业练习
作业:Docker安装Nginx
#1、搜索镜像#2、下载镜像 pull#3、运行测试[root@localhost home]# docker pull nginxUsing default tag: latestlatest: Pulling from library/nginx33847f680f63: Already existsdbb907d5159d: Pull complete8a268f30c42a: Pull completeb10cf527a02d: Pull completec90b090c213b: Pull complete1f41b2f2bf94: Pull completeDigest: sha256:8f335768880da6baf72b70c701002b45f4932acae8d574dedfddaf967fc3ac90Status: Downloaded newer image for nginx:latestdocker.io/library/nginx:latest#-d 后台运行#--name 给容器命名#-p 暴露端口 宿主机端口:容器内部端口[root@localhost home]# docker run -d --name nginx01 -p 3344:80 nginx3960a4e43a0252633d1b61f16902bd3926b43111e390b0d812a4daa0544656ac[root@localhost home]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES3960a4e43a02 nginx "/docker-entrypoint.…" 15 seconds ago Up 14 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01[root@localhost home]# curl localhost:3344<!DOCTYPE html><html><head><title>Welcome to nginx!</title><style>body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;}</style></head><body><h1>Welcome to nginx!</h1><p>If you see this page, the nginx web server is successfully installed andworking. Further configuration is required.</p><p>For online documentation and support please refer to<a href="http://nginx.org/">nginx.org</a>.<br/>Commercial support is available at<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p></body></html>#进入Nginx容器[root@localhost home]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES3960a4e43a02 nginx "/docker-entrypoint.…" 9 minutes ago Up 9 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01[root@localhost home]# docker exec -it nginx01 /bin/bashroot@3960a4e43a02:/# whereis nginxnginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginxroot@3960a4e43a02:/# cd /etc/nginx/root@3960a4e43a02:/etc/nginx# lsconf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_paramsroot@3960a4e43a02:/etc/nginx#


思考问题:我们每次改动Nginx配置文件,都需要进入容器内部,很麻烦,我要是可以在容器外部提供一个映射路径,达到在容器外部修改文件,容器内部就可以自动修改?? -v 数据卷技术!
作业:部署Tomcat
#官方的使用 run -it --rm tomcat:9.0docker run -it --rm tomcat:9.0#我们之前的启动都是后天启动,停止了容器之后,容器还是可以查到,docker run -it --rm 一般用来测试,用完就删除#下载启动docker pull tomcat#启动运行docker run -d -p 3355:8080 --name tomcat01 tomcat#用完就删除的方式测试[root@localhost home]# docker run -it --rm tomcat:9.0Unable to find image 'tomcat:9.0' locally9.0: Pulling from library/tomcat627b765e08d1: Pull completec040670e5e55: Pull complete073a180f4992: Pull completebf76209566d0: Pull completef10db7ba7580: Pull complete5b2f970878fa: Pull completeed434bfebf18: Pull completef6c437110aa9: Pull completea772951f83db: Pull complete752225c3768e: Pull completeDigest: sha256:6e40250d8fac4eca05c2067cb81f79427e4ddbaf4e78d5ecd21c35e8c5f2bfcfStatus: Downloaded newer image for tomcat:9.0Using CATALINA_BASE: /usr/local/tomcatUsing CATALINA_HOME: /usr/local/tomcatUsing CATALINA_TMPDIR: /usr/local/tomcat/tempUsing JRE_HOME: /usr/local/openjdk-11Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jarUsing CATALINA_OPTS:#启动运行[root@localhost home]# docker run -d -p 3355:8080 --name tomcat01 tomcat:9.048e19c70ce022167ea3c69bdbe61195a622f858f63985af01335ddfe1dbc0de4[root@localhost home]# docker exec -it tomcat01 /bin/bashroot@48e19c70ce02:/usr/local/tomcat# llbash: ll: command not found#发现问题:1、Linux命令少了 2、webapps中没有部署应用。 由于镜像的原因这里的命令是缺少的,默认镜像要保证最小可运行环境的安装,所以有些东西是被剔除掉了root@48e19c70ce02:/usr/local/tomcat# lsBUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.distCONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps workroot@48e19c70ce02:/usr/local/tomcat# cd webappsroot@48e19c70ce02:/usr/local/tomcat/webapps# ls#这个webapps下面是没有部署任何应用的root@48e19c70ce02:/usr/local/tomcat/webapps# cd ..root@48e19c70ce02:/usr/local/tomcat# cd webapps.dist/root@48e19c70ce02:/usr/local/tomcat/webapps.dist# lsROOT docs examples host-manager managerroot@48e19c70ce02:/usr/local/tomcat/webapps.dist# cd ..root@48e19c70ce02:/usr/local/tomcat# cp -r webapps.dist/* webapps #将webapps.dist文件下的拷贝到webapps部署应用root@48e19c70ce02:/usr/local/tomcat# cd webappsroot@48e19c70ce02:/usr/local/tomcat/webapps# lsROOT docs examples host-manager manager#这里就部署好了tomcat 映射端口号是3355

思考问题:以后如果需要用docker部署tomcat,然后需要在tomcat上部署我们自己的应用,就需要进入容器,非常的麻烦。
所以还是那个问题。可以在容器外部提供一个映射路径,webapps,我们在外部部署项目,就自动同步到内部就好了!
作业:部署es+kibana
#es 暴露的端口很多!#es 十分的耗内存#es 的数据一般需要放置到安全目录!挂载#docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag# --net somenetwork ? docker网络配置#启动elasticsearchdocker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2[root@localhost ~]# curl localhost:9200{"name" : "8da72f00f4a3","cluster_name" : "docker-cluster","cluster_uuid" : "8cTmM07VR8ezLtoZUQUw9g","version" : {"number" : "7.6.2","build_flavor" : "default","build_type" : "docker","build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f","build_date" : "2020-03-26T06:34:37.794943Z","build_snapshot" : false,"lucene_version" : "8.4.0","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"}#此时仅仅es就占用了1.2个G的内存#使用docker stats 来查看内存 以及cpu的状态#赶紧关闭,增加内存的限制,修改配置文件 -e 环境配置修改 最小内存64m 最大内存512mdocker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node"-e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS68fd7232219b elasticsearch02 0.44% 392MiB / 3.685GiB 10.39% 648B / 0B 0B / 696kB 47^C[root@localhost ~]# curl localhost:9200{"name" : "68fd7232219b","cluster_name" : "docker-cluster","cluster_uuid" : "P9WkyzOdT564mq2b0_sdAQ","version" : {"number" : "7.6.2","build_flavor" : "default","build_type" : "docker","build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f","build_date" : "2020-03-26T06:34:37.794943Z","build_snapshot" : false,"lucene_version" : "8.4.0","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"}


作业:使用kibana连接es 思考网络如何才能连过去!
可视化
portainer (先用这个)
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图形化界面管理工具!提供一个后台面板供我们操作!
[root@localhost ~]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainerUnable to find image 'portainer/portainer:latest' locallylatest: Pulling from portainer/portainer94cfa856b2b1: Pull complete49d59ee0881a: Pull completea2300fd28637: Pull completeDigest: sha256:fb45b43738646048a0a0cc74fcee2865b69efde857e710126084ee5de9be0f3fStatus: Downloaded newer image for portainer/portainer:latest6fd8a8735359499d8d0bc0990fd636a963653242fd781055a2c3ec6adb1e1ae2
访问外网测试:ip:192.168.150.131:8088
进入之后选择本地
镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包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。
平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用的host的kernel,自己只需要提供一个rootfs就可以了。由此可见对于不同的Linux发行版,bootfs是基本一致的,rootfs会有差距,因此不同的发行版可以直接公用bootfs。
分层理解
思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处,就是资源共享。比如说有多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了。而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过docker image inspect命令
[root@localhost ~]# docker image inspect redis:latest"Layers": ["sha256:814bff7343242acfd20a2c841e041dd57c50f0cf844d4abd2329f78b992197f4","sha256:dd1ebb1f5319785e34838c7332a71e5255bda9ccf61d2a0bf3bff3d2c3f4cdb4","sha256:11f99184504048b93dc2bdabf1999d6bc7d9d9ded54d15a5f09e36d8c571c32d","sha256:e461360755916af80821289b1cbc503692cf63e4e93f09b35784d9f7a819f7f2","sha256:45f6df6342536d948b07e9df6ad231bf17a73e5861a84fc3c9ee8a59f73d0f9f","sha256:262de04acb7e0165281132c876c0636c358963aa3e0b99e7fbeb8aba08c06935"]
理解:
所有的Docker镜像都起始于一个基础镜像层,当进行修改或者增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu创建一个新的镜像,这就是新镜像的第一层,如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层,如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含了3个镜像层,如图所示:
上图中的镜像层跟之前途中的略有区别,主要目的是便于展示文件。
下图中展示了稍微复杂的三层镜像,在外部看来整个镜像只有六个文件,这是因为最上层的文件7是文件5的一个更新版本
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像中。
Docker通过存储引擎(新版本采用快照机制)的方式实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、OVERLAY2、DEVICE MAPPER等,顾名思义,每种存储引擎都是基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都具有独有的性能特点。
特点:Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层就是容器层,容器之下位镜像层。你的所有操作都是基于容器层的。
commit镜像
如何提交一个自己的镜像
docker commit 提交容器成为一个新的副本#命令和git原理类似docker commit -m="提交的描述信息" -a="作者" 容器ID 目标镜像名:[TAG] 镜像名不可以有大写字母[root@localhost ~]# docker commit -m="ADD WEBAPPS APP" -a="guohaibo" 4d00846e722e tomcatweb:1.0sha256:40dba6e2662f8945e1d4296dceb6b53ff87bde37e29ccb8e729715073ca5cf16
到了这里才算入门docker ,容器数据卷、dockerFile 、Docker网络才是核心要学的东西。
三体中的一句话:弱小和无知不是生存的障碍,傲慢才是!
