Docker学习
Docker概述
安装教程:(https://docs.docker.com/engine/install/centos/)
文档(十分详细):(https://docs.docker.com/)
仓库地址:(https://hub.docker.com/signup)
Docker的出现。
一款产品有两个环境:开发和上线
发布以一个项目(jar+(redis,mysql,jdk,es,hadoop)),项目不能带上环境打包。环境配置麻烦,不能跨平台。
开发打包部署上线,一套流程做完。
Java —jar(环境)—打包项目带上环境(镜像)—(docker仓库:商店)—下载我们发布的镜像,直接运行即可
Docker给以上的问题提出了解决方案!
Docker通过隔离机制,隔离不同的应用,可以将服务器利用到极致!
docker历史(容器技术)
1.受欢迎的原因:十分轻巧
在容器技术出现之前都是使用虚拟机技术
虚拟机:使用一个软件,通过这个软件可以虚拟出来一台或者多台电脑。
docker容器技术,也是一种虚拟化技术。
docker能做什么?
虚拟机技术的缺点:
- 资源占用多
- 冗余步骤多
- 启动很慢
容器化技术:
容器化技术不是模拟的一个完整的操作系统
比较Docker和虚拟机的不同:
- 传统的虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个操作者系统上安装和运行软件
- 容器内的应用直接运行在宿主机上,容器时没有自己的内核的,也没有虚拟我们的硬件,所以轻便。
- 每个容器之间时隔离的,每个容器内都有一个自己的文件系统,互不影响。
devops(开发,运维)
应用更快的交付和部署
更快捷的审计和扩缩容
更简单的系统运维
更高效的计算资源利用
Docker时内核级别的虚拟化,可以在一个物理机上运行很多的容器实例,服务器的性能可以被压榨到极致!
Docker安装
Docker组成:
镜像:
一个docker镜像好比一个模板,可以通过这个模板来创建容器服务,tomcat镜像===>run===>tomcat01容器(提供服务器)
通过这个镜像看可以创建多个容器(最终服务运行或者运行就是在容器中的)。
仓库:
就是存放镜像的地方。仓库分为共有仓库和私有仓库。DockerHub(默认时国外的)
阿里云。。。都有容器容器服务(可以配置镜像加速!)
容器:
Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的。
启动,停止,删除,基本命令
目前就可以把这个容器理解为就是一个建议的Linux系统
安装
1.环境准备:
- 需要会Linux基础
- CentOs
- 使用Xshell连接远程服务器进行操作
2.环境查看
系统内核:
[root@iZ2zehsabv9z6btgwpsyhgZ ~]# uname -r
3.10.0-957.21.3.el7.x86_64
系统版本:
[root@iZ2zehsabv9z6btgwpsyhgZ ~]# cat /etc/os-release
NAME="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
#4. 更新docker软件包的索引
yum makecache fast
#5. 安装docker引擎-docker-ce是社区,ee是企业版
yum install docker-ce docker-ce-cli containerd.io
#6.启动docker
systemctl start docker
#7查看是否安装成功
docker version
#8.测试hello-world
docker run hello-world
#9.查看dockers下载的holle world镜像
docker images
#[root@iZ2zehsabv9z6btgwpsyhgZ ~]# docker images
#REPOSITORY TAG IMAGE ID CREATED SIZE
#redis latest aa4d65e670d6 10 days ago 105MB
#hello-world latest d1165f221234 5 months ago 13.3kB
了解:
#1.卸载docker依赖
yum remove docker-ce docker-ce-cli contain.io
#2.卸载docker环境资源
rm -rf /var/lib/docker
#/var/lib/docker 的docker默认资源路径
阿里云镜像加速配置:
配置使用:4步
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://2qs6lhsp.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
底层原理
Docker是怎么工作的?
Docker是一个Client-server结构的系统,Docker的守护进程运行在主机上,通过socket客户端访问。
Docker Server接受到Docker-client的指令,就会执行这个命令
Docker什么比vm快?
1.Docker有着比虚拟机更少的抽象层
2.docker利用的时宿主机的内核,vm需要的是Guest OS,分钟级别的启动,而docker是利用宿主机的操作系统,省略了这个复杂的过程,新建容器的过程是秒级的
Docker常用命令
帮助命令
docker version #显示docker 的版本信息
docker info #显示docker的系统信息 ,包括镜像和容器的数量
docker 命令 --help #万能命令
systemctl start docker #开启docker
systemmctl restart docker #重启docker
帮助文档地址:(https://docs.docker.com/reference/)
镜像命令
- docker images
[root@iZ2zehsabv9z6btgwpsyhgZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest aa4d65e670d6 10 days ago 105MB
hello-world latest d1165f221234 5 months ago 13.3kB
#解释
REPOSITORY:镜像的仓库源
TAG:镜像的标签
IMAGE ID:镜像的id
CREATED:镜像的创建时间
SIZE:镜像的大小
#常用可选项
-a, --all #列出所有镜像
-q, --quiet #只显示镜像的id
2.docker search #搜索镜像的命令,和在dockerHub网页上搜索是一样的。
如: docker search mysql
#可选项
-f, --filter filter #过滤操作
#如:--filter=STARS=3000 这个搜索出来的镜像就是stars大于3000的
#[root@iZ2zehsabv9z6btgwpsyhgZ ~]# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11205 [OK]
mariadb MariaDB Server is a high performing open sou… 4259 [OK]
3.docker pull 下载镜像
#docker pull 镜像名[:tag](指定版本,不然下载的都是最新版)
docker rmi 删除镜像
#删除指定镜像
[root@iZ2zehsabv9z6btgwpsyhgZ ~]# docker rmi -f 镜像id1
[root@iZ2zehsabv9z6btgwpsyhgZ ~]# docker rmi -f c60d96bd2b77
#批量删除镜像多个镜像
[root@iZ2zehsabv9z6btgwpsyhgZ ~]# docker rmi -f 镜像id1 镜像id2 镜像id3
[root@iZ2zehsabv9z6btgwpsyhgZ ~]# docker rmi -f $(docker images -aq) #删除所有镜像
容器命令
说明:有了镜像才可以创建容器,Linux,下载一个centOS镜像来测试学习
docker pull centos
新建容器并启动
1.docker run[可选参数] 镜像名
#参数说明
--name="Name" 容器名字 tomcat01 tomcat02,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P 随机指定端口
#启动并进入容器
[root@rookieWRL ~]# docker run -it centos /bin/bash #“rookieWRL”是我的服务器主机名
[root@7408b6254dde /]# #“7408b6254dde”是容器id
检验:
[root@rookieWRL ~]# docker run -it centos /bin/bash #启动容器
[root@3fcaef4607bc /]# [root@rookieWRL ~]# docker ps #查看当前在运行的容器(docker ps)需要切换到当前主机环境中才可以执行 -> 容器不停止退出(按ctrl+P+Q快捷键)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3fcaef4607bc centos "/bin/bash" 14 seconds ago Up 13 seconds inspiring_satoshi
[root@rookieWRL ~]# docker run -it centos /bin/bash
[root@ca140cb4cb87 /]# ls #查看容器内的centos 内部的centos和外部的没有任何关系,并且内部的centos有很多命令都不是完善的!
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
2.exit #退出容器到主机
3.docker ps #查看当前在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的容器
-q #只显示容器的id
4.退出容器
1.exit #直接退出容器
2.ctrl+P+Q快捷键 #容器不停止退出
5.删除容器
docker rm #删除删除一个或多个指定的容器 不能删除一个在运行的容器
docker rm -f #删通过 SIGKILL 信号强制删除一个运行中的容器。
docker rm $(docker ps -a -q) #删除所有已经停止的容器
docker ps -a -q|xargs docker rm #删除所有的容器
6.启动和停止容器
docker start #容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器
其他常用命令
1.后台启动容器
# 命令 docker run -d 镜像名
docker run -d centos
**********
#问题:docker ps 发现centos 停止了
#常见的坑:docker容器使用后台运行,就必须要一个前要运行,docker 发现没有应用就会自动停止
#nignx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
2.查看日志命令
命令:docker logs -tf --tail 容器id
#自己写一段shell脚本
docker run -d centos /bin.sh -c "while true;do echo rookieWRL;sleep 1;done"
#显示日志
-tf
--tail number(要显示的日志条数)
docker logs -tf --tail 10([日志条数]) 容器id
3.查看容器中的进程信息ps
命令:dockers top 容器id
[root@rookieWRL ~]# docker top 6d3671f6e27b
UID PID PPID C STIME TTY
root 8099 8081 0 17:06 pts/0
4.查看镜像的元数据
命令:docker inspect 容器id
[root@rookieWRL ~]# docker inspect 6d3671f6e27
[
{
"Id": "6d3671f6e27b9f7725763d51dc081293de63ca834ee37ceaa83f354b01b87c8e",
"Created": "2021-08-04T09:06:51.976114719Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 8099,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-08-04T09:06:52.390489038Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/6d3671f6e27b9f7725763d51dc081293de63ca834ee37ceaa83f354b01b87c8e/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/6d3671f6e27b9f7725763d51dc081293de63ca834ee37ceaa83f354b01b87c8e/hostname",
"HostsPath": "/var/lib/docker/containers/6d3671f6e27b9f7725763d51dc081293de63ca834ee37ceaa83f354b01b87c8e/hosts",
"LogPath": "/var/lib/docker/containers/6d3671f6e27b9f7725763d51dc081293de63ca834ee37ceaa83f354b01b87c8e/6d3671f6e27b9f7725763d51dc081293de63ca834ee37ceaa83f354b01b87c8e-json.log",
"Name": "/brave_haslett",
"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,
"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/8de9eeed955194496313f97bb0d54ba0c13f9787b8fae4e8ba1a07be03c014da-init/diff:/var/lib/docker/overlay2/e4b54ef4dd05eda469391646d67d0fbd65d2c38fc0bb46821737fd238ed66345/diff",
"MergedDir": "/var/lib/docker/overlay2/8de9eeed955194496313f97bb0d54ba0c13f9787b8fae4e8ba1a07be03c014da/merged",
"UpperDir": "/var/lib/docker/overlay2/8de9eeed955194496313f97bb0d54ba0c13f9787b8fae4e8ba1a07be03c014da/diff",
"WorkDir": "/var/lib/docker/overlay2/8de9eeed955194496313f97bb0d54ba0c13f9787b8fae4e8ba1a07be03c014da/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "6d3671f6e27b",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"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": "5e0af768a5e4a8493eb2dc9c889592eb89dea09ad3447ce0cb6528f5731ab39e",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/5e0af768a5e4",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "622da14a19c4f78294f0c7cb08870985bec3694ec56bdcdb1e0f63b4e4f0da27",
"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": "52610b926c5e1219293b38a25dba6e1fe3ceb26a0b26b6318f091a1e5617a171",
"EndpointID": "622da14a19c4f78294f0c7cb08870985bec3694ec56bdcdb1e0f63b4e4f0da27",
"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
}
}
}
}
]
5.进入当前正在运行的容器
#通常我们的容器都是i使用后台方式运行的,需要进入容器,修改一些配置
#命令
docker exec -it 容器id shell命令
[root@rookieWRL ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d3671f6e27b centos "/bin/bash" 16 minutes ago Up 16 minutes brave_haslett
3fcaef4607bc centos "/bin/bash" 2 hours ago Up 2 hours inspiring_satoshi
[root@rookieWRL ~]# docker exec -it 6d3671f6e27b /bin/bash
[root@6d3671f6e27b /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@6d3671f6e27b /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:06 pts/0 00:00:00 /bin/bash
root 16 0 0 09:23 pts/1 00:00:00 /bin/bash
root 31 16 0 09:24 pts/1 00:00:00 ps -ef
#方式二
命令:docker attach 容器id
正在执行当前代码
#docker exec 进入容器后并开启一个新的终端,可以在里面操作(常用)
#docker attach 进入容器正在执行的终端,不会启动新的进程
6.从容器内拷贝文件到主机上
命令:docker cp 容器id:容器内路径 目的主机路径
[root@rookieWRL ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d3671f6e27b centos "/bin/bash" 21 minutes ago Up 21 minutes brave_haslett
3fcaef4607bc centos "/bin/bash" 2 hours ago Up 2 hours inspiring_satoshi
[root@rookieWRL ~]# docker attch 6d3671f6e27b
docker: 'attch' is not a docker command.
See 'docker --help'
[root@rookieWRL ~]# docker attach 6d3671f6e27b
[root@6d3671f6e27b /]# cd /home
[root@6d3671f6e27b home]# touch cpfile.txt
[root@6d3671f6e27b home]# ls
cpfile.txt
[root@6d3671f6e27b home]# exit
exit
[root@rookieWRL ~]# cd /home
[root@rookieWRL home]# ls
redis www
[root@rookieWRL home]# docker ps 6d3671f6e27b:/home/cpfile.txt/home
"docker ps" accepts no arguments.
See 'docker ps --help'.
Usage: docker ps [OPTIONS]
List containers
[root@rookieWRL home]# docker cp 6d3671f6e27b:/home/cpfile.txt/home
"docker cp" requires exactly 2 arguments.
See 'docker cp --help'.
Usage: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
Copy files/folders between a container and the local filesystem
[root@rookieWRL home]# docker cp 6d3671f6e27b:/home/cpfile.txt /home
[root@rookieWRL home]# ls
cpfile.txt redis www
#拷贝是一个手动过程,未来我们使用-v卷的技术可以实现,自动同步
7.部署nginx
#1.搜索镜像:
[root@rookieWRL ~]# docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 15262 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 2054 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 815 [OK]
jc21/nginx-proxy-manager Docker container for managing Nginx proxy ho… 228
linuxserver/nginx An Nginx container, brought to you by LinuxS… 150
tiangolo/nginx-rtmp Docker image with Nginx using the nginx-rtmp… 137 [OK]
jlesage/nginx-proxy-manager Docker container for Nginx Proxy Manager 127 [OK]
alfg/nginx-rtmp NGINX, nginx-rtmp-module and FFmpeg from sou… 103 [OK]
jasonrivers/nginx-rtmp Docker images to host RTMP streams using NGI… 92 [OK]
nginxdemos/hello NGINX webserver that serves a simple page co… 70 [OK]
privatebin/nginx-fpm-alpine PrivateBin running on an Nginx, php-fpm & Al… 56 [OK]
nginx/nginx-ingress NGINX and NGINX Plus Ingress Controllers fo… 55
nginxinc/nginx-unprivileged Unprivileged NGINX Dockerfiles 46
staticfloat/nginx-certbot Opinionated setup for automatic TLS certs lo… 24 [OK]
schmunk42/nginx-redirect A very simple container to redirect HTTP tra… 19 [OK]
nginx/nginx-prometheus-exporter NGINX Prometheus Exporter for NGINX and NGIN… 19
centos/nginx-112-centos7 Platform for running nginx 1.12 or building … 15
centos/nginx-18-centos7 Platform for running nginx 1.8 or building n… 13
raulr/nginx-wordpress Nginx front-end for the official wordpress:f… 13 [OK]
bitwarden/nginx The Bitwarden nginx web server acting as a r… 11
flashspys/nginx-static Super Lightweight Nginx Image 10 [OK]
mailu/nginx Mailu nginx frontend 9 [OK]
sophos/nginx-vts-exporter Simple server that scrapes Nginx vts stats a… 7 [OK]
ansibleplaybookbundle/nginx-apb An APB to deploy NGINX 2 [OK]
wodby/nginx Generic nginx 1 [OK]
#2.下载镜像:
[root@rookieWRL ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
33847f680f63: Already exists
dbb907d5159d: Pull complete
8a268f30c42a: Pull complete
b10cf527a02d: Pull complete
c90b090c213b: Pull complete
1f41b2f2bf94: Pull complete
Digest: sha256:8f335768880da6baf72b70c701002b45f4932acae8d574dedfddaf967fc3ac90
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
#3.查看镜像是否下载成功
[root@rookieWRL ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest aa4d65e670d6 12 days ago 105MB
nginx latest 08b152afcfae 13 days ago 133MB
hello-world latest d1165f221234 5 months ago 13.3kB
centos latest 300e315adb2f 7 months ago 209MB
#4.运行容器
-d 后台运行
--name 给容器命名
-p 宿主机端口,容器内端口映射
[root@rookieWRL ~]# docker run -d --name nginx01 -p 3344:80 nginx
4f5f39163906c9aeb09c8c829cb6f3a3af1ba874bc95830b6f1a2f1a4470e9c4
#5.查看正在运行的容器
[root@rookieWRL ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4f5f39163906 nginx "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 0.0.0.0:3344->80/tcp nginx01
3fcaef4607bc centos "/bin/bash" 6 hours ago Up 6 hours inspiring_satoshi
#6测试接口-访问3344端口-curl命令可以直接在终端进行测试
[root@rookieWRL ~]# curl localhost:3344
#进入容器
[root@rookieWRL ~]# docker exec -it nginx01 /bin/bash
#查看nginx相关文件的位置
root@4f5f39163906:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
#查看nignx相关的配置文件
root@4f5f39163906:/# cd /etc/nginx
root@4f5f39163906:/etc/nginx# ls
conf.d mime.types nginx.conf uwsgi_params
fastcgi_params modules scgi_params
端口暴露的概念
怎么在容器外部修改容器内的nginx配置文件?–数据卷的技术
8.部署tomcat
#官方启动方法:我们之前的启动都是是后台的,用完停止容器之后,容器还是可以查到的,docker run -it --rm 一般用来测试,用完及删除,用完这个容器就会删除这个容器
$ docker run -it --rm tomcat:9.0
#下载启动
docker pull tomcat
#启动tomcat
[root@rookieWRL ~]# docker run -d -p 3355:8080 --name tomcat01 tomcat
2e9abd39f97011c61310c19e2854db862c1b6ed44c43f30af673c69cb47496fb
#测试外部主机访问该tomcat
问题:没有网站,所以找不到页面
#进入容器
[root@rookieWRL ~]# docker exec -it tomcat01 /bin/bash
root@2e9abd39f970:/usr/local/tomcat# ls
BUILDING.txt NOTICE RUNNING.txt lib temp work
CONTRIBUTING.md README.md bin logs webapps
LICENSE RELEASE-NOTES conf native-jni-lib webapps.dist
root@2e9abd39f970:/usr/local/tomcat# ls -al
total 176
drwxr-xr-x 1 root root 4096 Jul 23 09:46 .
drwxr-xr-x 1 root root 4096 Aug 7 10:15 ..
-rw-r--r-- 1 root root 18949 Jun 28 08:46 BUILDING.txt
-rw-r--r-- 1 root root 6210 Jun 28 08:46 CONTRIBUTING.md
-rw-r--r-- 1 root root 57092 Jun 28 08:46 LICENSE
-rw-r--r-- 1 root root 2333 Jun 28 08:46 NOTICE
-rw-r--r-- 1 root root 3372 Jun 28 08:46 README.md
-rw-r--r-- 1 root root 6898 Jun 28 08:46 RELEASE-NOTES
-rw-r--r-- 1 root root 16507 Jun 28 08:46 RUNNING.txt
drwxr-xr-x 2 root root 4096 Jul 23 09:46 bin
drwxr-xr-x 1 root root 4096 Aug 7 10:15 conf
drwxr-xr-x 2 root root 4096 Jul 23 09:46 lib
drwxrwxrwx 1 root root 4096 Aug 7 10:15 logs
drwxr-xr-x 2 root root 4096 Jul 23 09:46 native-jni-lib
drwxrwxrwx 2 root root 4096 Jul 23 09:46 temp
drwxr-xr-x 2 root root 4096 Jul 23 09:46 webapps
drwxr-xr-x 7 root root 4096 Jun 28 08:46 webapps.dist
drwxrwxrwx 2 root root 4096 Jun 28 08:46 work
root@2e9abd39f970:/usr/local/tomcat# cd webapps
root@2e9abd39f970:/usr/local/tomcat/webapps# ls
root@2e9abd39f970:/usr/local/tomcat/webapps#
#发现问题:发现这个容器是被阉割过的
#1.Linux命令少了
#2.没有webapps。阿里云的原因,默认是最小的镜像,所以不必要的都去除了
#保证了最小的可运行环境
#进入webapps.dist文件夹,这个是它的输出目录 ,然后把里面的内容拷贝到webapps里面
root@2e9abd39f970:/usr/local/tomcat# cd webapps.dist
root@2e9abd39f970:/usr/local/tomcat/webapps.dist# ls
ROOT docs examples host-manager manager
root@2e9abd39f970:/usr/local/tomcat/webapps.dist# cd ..
root@2e9abd39f970:/usr/local/tomcat# cp webapps.dist/* webapps
cp: -r not specified; omitting directory 'webapps.dist/ROOT'
cp: -r not specified; omitting directory 'webapps.dist/docs'
cp: -r not specified; omitting directory 'webapps.dist/examples'
cp: -r not specified; omitting directory 'webapps.dist/host-manager'
cp: -r not specified; omitting directory 'webapps.dist/manager'
root@2e9abd39f970:/usr/local/tomcat# cd webapps
root@2e9abd39f970:/usr/local/tomcat/webapps# ls
root@2e9abd39f970:/usr/local/tomcat/webapps# cd ..
root@2e9abd39f970:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@2e9abd39f970:/usr/local/tomcat# cd webapps
root@2e9abd39f970:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
#拷贝过来之后就可以访问到了
怎么在容器外部提供一个映射路径,webapps,我们在外部放置项目,就自动同步到内部就好了?
9.怎么部署es+kibana
#es暴露的接口很多!
#es十分耗内存
#es的一般数据需要放置到安全目录!挂载
#--net somenetwork 网络配置
#下载启动 elasticsearch
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
#启动了Linux就会卡
docker stats ->查看cpu状态
#es十分耗内存
#测试es是否安装成功
[root@rookieWRL ~]# curl localhost:9200
{
"name" : "dc59c39551d1",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "pS9kjEM9T1aWYkED6SZy_Q",
"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,增加内存的限制 ,修改配置文件 -e环境配置修改
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
错误1:
docker: Error response from daemon: Conflict. The container name "/elasticsearch" is already in use by container "dc59c39551d11c7a71e862347b8d17841452139f7d61f53051ada086d258e129". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
解决:表示这个名为“elasticsearch”的容器已经存在,我们取一个别的名字即可
错误2:在想要修改配置并运行es时出现以下错误:
[root@rookieWRL ~]# docker run -d --name elasticsearch03 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
82744712a58bd2d41a2ac14ec7b171f2d6f2d4b8a8b68c492800d490d922942e
docker: Error response from daemon: driver failed programming external connectivity on endpoint elasticsearch03 (79dae940d2e994c7d789b8789fb0b6c1b71d746bdc65c4e0bde88363b0f3004d): Bind for 0.0.0.0:9300 failed: port is already allocated.
解决:因该是有es容器占用了9300端口,我把正在运行的es容器停掉重新运行就好了
#重新配置后测试成功
[root@rookieWRL ~]# curl localhost:9200
{
"name" : "cded944be5f7",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "jCQIP0nGTKq_hfkxDVP73A",
"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
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图形化管理工具。提供一个后台面板给我们操作
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
- 参数说明:
- –restart=always 启动方式
- -v /var/run/docker.sock:/var/run/docker.sock 挂载
- –privileged=true 权限
访问测试:
外网:http://39.105.163.53:8088/
注册页面:
注册之后:
local
平时不会使用这个面板
Docker镜像讲解
镜像是什么?
镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
所有应用直接打包docker镜像,就可以直接跑起来!
如何得到镜像:
1.从远程下载
2.朋友拷贝过来
3.自己制作一个镜像dockerFile
Docker镜像加载原理
UnionFS(联合文件系统)
UnionFs(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统。它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同的目录挂载到同一个虚拟文件系统下(unite serveral directories into a single virtual filesystem).Union文件系统是docker 镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS.
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要引导加载kernel,Linux刚启动的时候会加载bootfs文件系统,在docker镜像的最底层就是bootfs。这一层与我们典型的Linux和Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs.
rootfs(root file system) ,在bootfs之上,包含的就是典型的Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如Ubuntu,centos等
平时安装的centos都是好几个G,为什么到docke这里才几百M
对于一个精简的OS,rootfs很小,只需包含最基本的命令,工具和程序库就可以了,因为最底层直接使用host的kernel,自己只需要提供rootfs就可以了,由此可见对于不同的Linux发行版本,bootfs基本是一致的,rootfs会有差别,因此不同的发行版本可以公用bootfs.
分层理解
分层的镜像
思考?为什么docker镜像要采用这种分层的结构呢?
最大的好处莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过docker imgae inspect命令!
理解:
所有的docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。举一个简单的例子。例如基于Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层,如果在该镜像中添加python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含三个镜像层,如下图:
在添加额外镜像蹭听的同时,镜像始终保持时当前所有镜像的组合,理解这一点十分重要,下图举了一个简单的例子,每个镜像层包含三个文件,二镜像包含了来自两个镜像层的6个文件。
上图的镜像层跟之前的略有区别,主要目的是便于展示文件。
下图展示另一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版
这种情况下,上层镜像层中的文件能覆盖了底层镜像层中的文件。这样就使得文件的更新本版作为一新的镜像层添加到镜像当中。Docker通过存储引擎(新版本采用快照机制)的方式实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可以用的存储引擎有AUFS,Overlay2,DeviceMapper,Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在windows上仅支持Windows filter一种存储引擎,该引擎基于NTFS文件系统之上是实现了分层和Cow[1]
下图展示 了与系统显示相同的三层镜像,所有镜像层堆叠并合并,对外提供统一的视图。
特点:
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下都叫镜像层
如何提交一个自己的镜像
commit镜像
docker commit 提交容器成为一个新的副本
#命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[版本]
实战测试:
1.启动一个默认的tomcat
2.发现这个默认的tomcat是 没有webapp应用,镜像的原因,官方的镜像默认,webapps下面是没有文件的
3.我们手动拷贝文件进去
4.将我们操作过的容器通过commit提交为一个镜像,我们以后就是用我们修改过的镜像即可。这就是我们自己的一个修改的镜像
到这才是入门docker
挂载类型
-
Volumes :数据卷(Volumes)存储在由 Docker 管理的主机文件系统的一个区域中(Linux上通常是/var/lib/docker/volumes/)。这部分文件系统是由 Docker 管理的,因此非 Docker 进程不应修改这部分文件系统。Volumes 是在 Docker 中持久化数据的最好方式。
-
Bind mounts:绑定挂载(Bind mounts)可以存储在主机系统的任何地方。它们甚至可以是重要的系统文件或目录。Docker 主机或 Docker 容器上的非 Docker 进程随时都可以修改它们。
-
tmpfs mounts: 临时文件系统挂载(tmpfs mounts)仅存储在主机系统的内存中,永远不会写入主机系统的文件系统中。
想要直观地理解 volume、绑定挂载(bind mount) 和 tmpfs 挂载之间的区别,可以考虑它们在Docker主机上的数据存储位置。
对于 volume,数据存储在 Docker 的存储系统中,由 Docker 自身管理。相反,绑定挂载是将主机的文件系统中的目录挂载到容器中,因此数据存储在主机上。此外,tmpfs 挂载类似于绑定挂载,但数据存储在内存中,而不是存储在主机文件系统上。
但无论使用哪种挂载类型,Docker 容器都能够像本地文件系统中的数据一样读取和写入数据。这确保了数据可以在容器之间或容器和主机系统之间轻松管理和共享。
挂载点
挂载点(mount point)是指在文件系统中将一个存储设备或文件系统挂载(连接)到目录结构的特定位置,以便可以访问该存储设备中的内容或文件系统中的文件。
在操作系统中,每个存储设备(如硬盘、分区、USB驱动器等)或文件系统都需要被挂载到一个具体的目录位置,以便操作系统和用户可以通过该目录来访问其中的数据。这个目录就是挂载点。
挂载点可以是任意空目录,它在文件系统中充当了一个节点,用于与特定的存储设备或文件系统之间建立连接。文件系统中可以有多个挂载点,每个挂载点都对应一个特定的存储设备或文件系统。
例如,在Linux系统中,可以将一个外部USB驱动器挂载到 /mnt/usb
目录下。这样,在访问 /mnt/usb
目录时,实际上是在访问该USB驱动器中的文件和数据。
挂载点是操作系统文件系统的重要概念,它提供了组织和访问存储设备或文件系统的方法,并使其能够在目录结构中成为可访问的一部分。
绑定挂载(Bind mounts)
绑定挂载(Bind mounts)自 Docker 的早期版本就已经存在了。与数据卷相比,绑定挂载的功能比较有限。当您使用绑定挂载时,会将主机机器上的某个文件或目录挂载到容器中。文件或目录由其在主机机器上的完整路径引用。该文件或目录不需要在 Docker 主机上事先存在。如果它尚不存在,则会按需创建。绑定挂载的性能非常良好,但它们依赖于主机机器的文件系统中有特定的目录结构可用。如果您正在开发新的 Docker 应用程序,建议使用命名卷(named volumes)来代替绑定挂载。您无法使用 Docker CLI 命令直接管理绑定挂载。
注意:绑定挂载(Bind mounts)可以通过在容器中运行的进程访问敏感文件
。
-v和–mount行为之间的差异
如果您使用-v或–volume绑定挂载 Docker 主机上尚不存在的文件或目录,-v则会为您创建端点。它始终创建为目录。
如果您使用–mount绑定挂载 Docker 主机上尚不存在的文件或目录,Docker 不会自动为您创建它,而是会生成错误。
挂载到容器上的非空目录中
如果将目录绑定挂载到容器上的非空目录中,则该目录的现有内容将被绑定挂载遮盖。
使用只读绑定挂载
通过添加到ro容器内挂载点之后的选项列表(默认为空),将目录挂载为只读绑定挂载
docker run -d -it --name devtest -v "$(pwd)"/target:/app:ro nginx:latest
或
docker run -d -it --name devtest --mount type=bind,source="$(pwd)"/target,target=/app,readonly nginx:latest
配置绑定传播
要配置绑定传播(bind propagation),可以在Linux主机上使用mount
命令以及适当的传播标志(propagation flag)和bind选项。
传播标志有以下几种选项:
- rprivate: 挂载是私有的,更改不会传播到其他挂载点。
- rshared: 挂载是共享的,更改会传播到其他挂载点。
- runbindable: 挂载可以根据原始挂载点的传播类型(propagation type)设置为私有或共享。
要为特定的绑定挂载配置绑定传播,可以使用以下命令:
mount --bind --make-rprivate /源路径 /目标路径
该命令将从源路径到目标路径创建一个绑定挂载,并将传播设置为私有。对挂载所做的更改不会传播到其他挂载点。
类似地,可以使用--make-rshared
将传播设置为共享,或使用--make-runbindable
以使它可根据原始挂载点的传播类型进行绑定。
请记住,绑定传播仅适用于绑定挂载,在Linux主机上可配置。对于大多数用户来说,不需要配置绑定传播,因为默认的rprivate设置对大多数场景已经足够。
- 什么是绑定传播
绑定传播(bind propagation)是指在一个绑定挂载中创建的挂载是否可以传播(或复制)到该挂载的副本中。当存在多个挂载点指向同一文件系统时,绑定传播确定了对其中一个挂载点所做的更改是否会传播到其他挂载点。
举个例子来说,假设有一个挂载点
/mnt
,同时也在/tmp
上进行了挂载。绑定传播设置控制着在/tmp/a
上进行挂载是否也会在/mnt/a
上可用。每个传播设置都有一个递归对应。以递归为例,考虑/tmp/a
也作为/foo
进行了挂载。绑定传播设置控制着/mnt/a
和/或/tmp/a
是否存在。
绑定传播的主要目的是控制共享文件系统中的挂载点之间的可见性和一致性。不同的绑定传播设置可以根据需要提供不同的行为。默认情况下,绑定传播设置为
rprivate
,即私有传播,表示更改不会传播到其他挂载点。其他可用的传播设置包括rshared
,即共享传播,表示更改会传播到其他挂载点,以及runbindable
,它可以根据原始挂载的传播类型设置挂载为私有或共享。
需要注意的是,绑定传播仅适用于绑定挂载,在Linux环境下可配置。对于大多数用户而言,通常不需要手动配置绑定传播,使用默认的传播设置即可满足大部分需求。
- 什么是挂载副本
一个挂载的副本是指通过绑定(bind)或共享(share)方式,将同一个文件系统挂载到不同的挂载点上。在这种情况下,通过将原始挂载点复制到其他位置,可以创建一个与原挂载点一致的文件系统视图。
例如,假设有一个挂载点
/mnt
上挂载了一个文件系统。然后,通过绑定传播或共享传播,将该挂载点的副本挂载到/tmp
上。通过这样的操作,/tmp
将成为/mnt
的一个副本。
这样,对于在
/mnt
上进行的更改也会反映在/tmp
上的副本中。如果在/tmp/a
上创建了一个新文件,这个文件会在
/mnt/a
中可见。类似地,如果在/mnt
上进行了文件删除操作,/tmp
上的副本也会反映这个更改。
挂载的副本可以在同一主机的不同位置提供对相同文件系统的访问,并且更改将在这些副本之间传播。这种机制使得在不同挂载点上进行同步读写操作成为可能
警告
挂载传播不适用于 Docker Desktop。
- 这些是关于挂载点(mount point)传播设置的描述:
shared
:原始挂载点的子挂载点会被暴露给副本挂载点,副本挂载点的子挂载点也会传播到原始挂载点。slave
:类似于shared
,但是只能单向传播。原始挂载点如果暴露一个子挂载点,副本挂载点可以看到它。然而,如果副本挂载点暴露一个子挂载点,原始挂载点则无法看到它。private
:挂载点是私有的。其中的子挂载点不会被传播到副本挂载点,副本挂载点的子挂载点也不会传播给原始挂载点。rshared
:与shared
相同,但传播还扩展到原始或副本挂载点嵌套的任何挂载点内。rslave
:与slave
相同,但传播也扩展到原始或副本挂载点嵌套的任何挂载点内。rprivate
:默认设置。与private
相同,意味着原始或副本挂载点内的任何挂载点都不会传播。
配置selinux标签
在使用SELinux时,您可以通过添加z
或Z
选项来修改被挂载到容器中的文件或目录的SELinux标签。这会影响主机机器上的文件或目录,并可能导致超出Docker范围的后果。
z
选项表示绑定挂载的内容在多个容器之间共享。Z
选项表示绑定挂载的内容是私有和非共享的。
请谨慎使用这些选项。使用Z
选项绑定挂载系统目录(如/home
或/usr
)可能导致主机机器无法操作,并且您可能需要手动重新标记主机机器的文件。
重要提示:当与服务一起使用时,bind挂载的selinux标签(:Z
和:z
)以及:ro
选项会被忽略。有关详细信息,请参阅moby/moby #32579。
以下示例使用z
选项,指定多个容器可以共享绑定挂载的内容:
docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app:z \
nginx:latest
需要注意的是,目前无法使用--mount
标志修改SELinux标签。
临时文件系统挂载(tmpfs mounts)
临时文件系统挂载(tmpfs mounts):在 Docker 主机或容器内部都不会将 tmpfs 挂载持久化到磁盘上。它可以在容器的生命周期内被容器使用,用于存储非持久化状态或敏感信息。例如,swarm 服务在内部使用 tmpfs 挂载将密钥挂载到服务的容器中。在使用 tmpfs 挂载时,需要注意不要将敏感信息存储在其中,因为一旦容器关闭,数据就会消失。
命名管道(named pipes)
命名管道(named pipes):npipe 挂载可用于 Docker 主机和容器之间的通信。常见的用例是在容器内运行第三方工具,并使用命名管道连接到 Docker 引擎 API。命名管道可以提供一种简单的方法,使容器内部的进程能够与 Docker 主机进行通信,而不需要将敏感信息通过网络发送。
数据卷(Volumes)
Volumes(数据卷)是由 Docker 创建和管理的。您可以使用 docker volume create 命令显式地创建数据卷,或者 Docker 可以在创建容器或服务时创建数据卷。
创建数据卷时,它会存储在 Docker 主机上的一个目录中。当您将数据卷添加到容器时,就会将这个目录挂载到容器内部。这类似于绑定挂载的工作方式,但是数据卷是由 Docker 管理的,与主机机器的核心功能隔离。
一个数据卷可以同时挂载到多个容器中。当没有任何正在使用某个数据卷的容器时,该数据卷仍然可供 Docker 使用,不会被自动删除。您可以使用 docker volume prune 命令来删除未使用的数据卷。
在挂载数据卷时,它可以有命名(named)或匿名(anonymous)。匿名数据卷在首次挂载到容器时不会被显式地命名,因此 Docker 会为它们分配一个随机的名称,该名称可以在给定的 Docker 主机内确保唯一。除了名称之外,命名和匿名数据卷的行为相同。
数据卷还支持使用卷驱动程序(volume drivers),这使您可以将其数据存储在远程主机或云服务提供商等位置。
什么是容器数据卷
docker 的理念: 将应用和环境打包成一个镜像
总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的!
volume绑定传播
在Docker中,容器可以通过挂载(volume)宿主机中的目录,来实现数据在容器和宿主机之间的共享。而绑定传播(bind propagation)则是指容器内的操作(新增、修改、删除)是否需要同步到宿主机上挂载的目录中,以及其他正在使用该volume的容器中。
在Docker中,使用volume的时候,有两种传播方式:
-
rprivate:表示volume仅在容器内有效,不会传播到宿主机或其他容器中。
-
rshared:表示volume会传播到其他所有与此volume挂载同一路径的容器中。
对于volume来说,只能使用rprivate传播方式,而bind propagation则无法配置。这是因为Docker认为,如此可以更好地隔离容器之间,保证数据安全。
-v和–mount
–mount: 由多个键值对组成,以逗号分隔,每个键值对由一个=元组组成。语法–mount比-v或者–volume更冗长,但键的顺序并不重要,标志的值更容易理解。
-
挂载类型(type):可以选择bind、volume或tmpfs。这里是针对volumes进行讨论,因此类型永远为volume。
-
源(source):对于命名的volume,这里是volume的名称。对于匿名volume,则省略此字段。可以使用source或src指定。
-
目的地(destination):该字段指定容器内挂载文件或目录的路径。可以使用destination、dst或target指定。
-
只读选项(readonly):如果指定,将会以只读方式将bind挂载到容器中。可以使用readonly或ro指定。
-
volume-opt选项:可以指定多个key-value形式的选项名称和值,以此来指定volume的一些额外选项。
使用数据卷
方式一:
直接使用用命令挂载
docker run -it -v 主机目录 :
容器内目录
docker run -it --name=nginxtest -v /home/ceshi:/home centos /bin/bash
如果启动一个创建新卷的容器,并且该容器在要挂载的目录中有文件或目录(例如 )/app/,则 Docker 会将目录的内容复制到该卷中。然后容器安装并使用该卷,并且使用该卷的其他容器也可以访问预填充的内容
在主机本地修改文件,容器内也会自动同步
实战:安装MySQL
docker pull mysql:5.7
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
-e :环境配置
#启动成功之后,我们在本地主机使用可视化工具 sqlyog 来测试一下。
#sqlyog连接到服务器的3310------3310和容器内的3306映射,这个时候我们就可以连接上了。
#在本地测试创建一个数据库,查看一下我们映射的路径是否ok
二、只读卷
容器只需要对数据进行读取访问。多个容器可以挂载同一个卷(volume)。你可以同时将单个卷设置为某些容器的读写模式,而对其他容器设置为只读模式。
容器只需要对数据进行读取访问。多个容器可以挂载同一个卷(volume)。你可以同时将单个卷设置为某些容器的读写模式,而对其他容器设置为只读模式。
docker run -d --name=nginxtest -v nginx-vol:/usr/share/nginx/html:ro nginx:latest
方式二:
初识dockerfile
载镜像生成时就挂载
方式三:使用卷驱动程序
可以指定卷驱动程序
以下示例vieux/sshfs首先在创建独立卷时使用卷驱动程序,然后在启动创建新卷的容器时使用卷驱动程序。
具名挂载和匿名挂载
多容器数据共享
多个MySQL同步数据
数据卷的备份、恢复和迁移
备份
Volumes对于备份、恢复和迁移非常有用。使用--volumes-from
标志创建一个新的容器,并将该卷挂载到新容器中。
以下是备份一个卷的示例:
首先,创建一个名为dbstore
的新容器,并将/dbdata
目录作为卷挂载到该容器中:
docker run -v /dbdata --name dbstore ubuntu /bin/bash
接下来的命令将完成以下操作:
- 启动一个新的容器,并将
dbstore
容器中的卷挂载到该容器中。 - 将本地主机目录挂载为
/backup
。 - 执行一个命令,将
dbdata
卷的内容使用tar命令打包为/backup/backup.tar
文件。
docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
当命令完成并容器停止时,它会创建dbdata
卷的备份,保存为backup.tar
文件在/backup
目录下。
通过使用--volumes-from
标志和docker run
命令可以在Docker中方便地进行卷的备份操作,确保数据的安全性和可靠性。
从备份恢复卷
使用刚刚创建的备份,您可以将其恢复到相同的容器或在其他地方创建的另一个容器中。
例如,创建一个名为dbstore2
的新容器:
docker run -v /dbdata --name dbstore2 ubuntu /bin/bash
然后,在新容器的数据卷中解压备份文件:
docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"
通过运行上述命令,您可以将备份文件解压到dbstore2
容器的/dbdata
目录中。
您可以使用上述技术和您喜欢的工具来自动化备份、迁移和恢复测试,以确保数据的安全性和可靠性。
删除卷
在删除容器后,Docker数据卷将持久存在。有两种类型的数据卷需要考虑:
- 命名卷(Named volumes):具有来自容器外的特定源,例如
awesome:/bar
。 - 匿名卷(Anonymous volumes):没有具体的源。因此,当删除容器时,您可以指示Docker引擎守护进程将其删除。
删除匿名卷
要自动删除匿名卷,可以使用--rm
选项。例如,以下命令创建了一个匿名的/foo
卷。当您删除容器时,Docker引擎将删除/foo
卷,但不会删除awesome
卷。
docker run --rm -v /foo -v awesome:/bar busybox top
注意:
如果另一个容器使用--volumes-from
绑定了卷,那么卷定义会被复制,即使第一个容器被删除后,匿名卷也将保留。
删除所有卷
要删除所有未使用的卷并释放空间,可以使用以下命令:
docker volume prune
通过运行上述命令,您可以删除所有未使用的Docker卷,以释放磁盘空间。请谨慎操作,确保不会删除您需要保留的卷。
存储驱动程序
Docker镜像由一系列层构成,每个层代表Dockerfile中的一条指令。除了最后一个层外,其他层都是只读的。
# syntax=docker/dockerfile:1
FROM ubuntu:22.04
LABEL org.opencontainers.image.authors="org@example.com"
COPY . /app
RUN make /app
RUN rm -r $HOME/.cache
CMD python /app/app.py
每个层只记录与前一个层的差异。需要注意的是,添加和删除文件都会产生一个新的层。在上面的示例中,$HOME/.cache
目录被删除,但它仍然存在于前一个层中,并会增加镜像的总体大小。
这些层会按顺序堆叠在一起。创建新容器时,会在基础层之上添加一个新的可写层,通常称为"容器层"。对正在运行的容器所做的所有更改(如创建新文件、修改现有文件和删除文件)都会写入这个薄的可写容器层。下面的图示显示了一个基于ubuntu:15.04
镜像的容器结构。
Thin R/W(read-write) layer(可写层)
Thin R/W(read-write) layer是指Docker容器中的可写层。当创建一个容器时,Docker会在底层的只读层之上添加一个新的可写层,这个可写层就是容器运行时的文件系统。
在容器中对文件系统的任何更改,如创建新文件、修改现有斜体样式文件或删除文件,都会在这个可写层中进行。这个可写层是一个薄的、紧凑的存储层,它只记录与底层只读层的差异。这种机制使得容器的文件系统更轻量级,同时允许容器在运行时对文件系统进行修改,而不影响底层镜像或其他容器的文件系统。
由于可写层是容器运行时的文件系统,在容器生命周期结束后,这个可写层会被丢弃,不会保存任何永久性的更改。这也是为什么在容器中存储持久化数据的最佳实践是使用Docker卷或绑定挂载,将数据保存在容器外部的持久化存储中。
Docker 使用存储驱动程序来管理镜像层和可写容器层的内容。每个存储驱动程序以不同的方式处理实现,但所有驱动程序都使用可堆叠图像层和写时复制(CoW)策略。
写时复制 (CoW) 策略 [Copy-on-write (CoW)]
是一种共享和复制文件的策略,以实现最大效率。
- 如果镜像的较低层中存在一个文件或目录,并且另一个层(包括可写层)需要对其进行读访问,它只需使用现有的文件。
- 当另一个层首次需要修改文件时(构建镜像或运行容器时),文件会被复制到该层并进行修改。这样可以最小化I/O操作和后续层的大小。以下更详细地解释了这些优势的含义。
使用Copy-on-write策略时,容器中的每个层都只包含与上一层不同的文件和目录。当多个容器共享同一个镜像时,它们共享相同的只读层,但每个容器都有自己的可写层来记录自己的更改。这样,多个容器可以在相同的基础镜像上运行,节省了存储空间,并且任何一个容器的更改都不会影响其他容器。
当多个容器共享相同的镜像时,它们共享相同的基础文件,并且不会复制多个副本。只有在容器需要进行写操作时,修改的文件才会被复制到该容器的可写层中。这样可以减少不必要的复制,节省了I/O操作和存储空间,提高了效率。
查看镜像的构建历史
docker image history 镜像名
某些步骤没有大小 ( 0B),并且是仅元数据的更改,不会生成图像层,并且除了元数据本身之外,不占用任何大小。
在Docker历史输出中的<missing>
行表示这些步骤是在另一个系统上构建的,并且作为从Docker Hub获取的alpine镜像的一部分,或者是使用BuildKit作为构建工具构建的。在BuildKit之前,传统的构建工具会为了缓存目的,为每个步骤生成一个新的"中间"镜像,并在IMAGE列中显示该镜像的ID。BuildKit使用自己的缓存机制,不再需要中间镜像进行缓存。请参考BuildKit以了解有关BuildKit的其他改进信息。
检查镜像的每个图层
使用docker image inspect命令查看每个镜像中各层的加密 ID:
请注意,两个图像中的前两层是相同的。第二张图像添加了两个附加层。共享镜像层仅存储一次,/var/lib/docker/并且在将镜像推送和拉取到镜像注册表时也会被共享。因此,共享图像层可以减少网络带宽和存储。
复制使容器变得高效
当容器中的现有文件被修改时,存储驱动程序执行拷贝写入操作。具体的步骤取决于特定的存储驱动程序。对于overlay2驱动程序,拷贝写入操作大致遵循以下顺序:
- 在镜像层中搜索要更新的文件。该过程从最新的层开始,逐层向下搜索到基础层。找到的结果会被添加到缓存中以加速后续的操作。
- 在找到的第一个文件的副本上执行复制操作,将文件复制到容器的可写层。
- 对这个文件副本进行任何修改,并且容器看不见位于较低层中的只读文件的副本。
Btrfs、ZFS和其他驱动程序以不同的方式处理拷贝写入。
写入大量数据的容器比不写入数据的容器占用更多的空间。这是因为大多数写操作会消耗容器的薄可写顶层的新空间。请注意,更改文件的元数据,例如更改文件权限或所有权,也可能导致复制写入操作,从而将文件复制到可写层中。
dokcerFile
dockerFile构建
dockerFile命令
镜像构建实战:
CMD和ENTRYPOINT的区别
实战制作tomcat镜像
发布自己的镜像
发布镜像到阿里云
参考阿里云文档
docker run -p 3306:3306 --name mysql
-v /data/docker/mysql/conf:/etc/mysql/conf.d
-e MYSQL_ROOT_PASSWORD=Vv0IBQ5qST
-d mysql:5.7
–link
自定义网络
网络连通
容器可写层
在容器技术中,每个容器都可以被看作是一个独立的进程,并且拥有自己的文件系统、网络、进程空间等资源。为了实现对容器的管理和控制,每个容器都有一个基础镜像(Base Image),该镜像包含了容器所需要的操作系统和应用程序环境。
当创建一个新的容器时,它会初始化一个可写层(Writeable Layer),它可以被看作是容器默认挂载的一个文件系统,用于在容器中保存所有的更改或修改。可写层的另一个作用是,使不同容器之间的修改相互隔离,从而保证每个容器的独立性和安全性。
可写层在容器中的作用类似于一个分层文件系统,容器的文件系统可以被看作由多个层次组成,每个层次包含了一个可写层和一个只读的基础镜像。当容器使用一个文件时,它首先在可写层中查找,如果不存在则会在只读层中查找。如果容器中有多个层次存在同名文件,则根据搜索层级的优先顺序,选择优先级最高的文件。
需要注意的是,每个可写层都是独立的,容器之间不共享可写层。当容器停止时,该层会被清理或销毁,任何修改都会丢失。为了保留对容器的修改或更改,用户需要使用Docker commit等命令将容器的状态保存为新的容器镜像,从而可以在以后的容器中使用该镜像。
实战部署redis集群
启动redis服务
docker使用apache pulsar
运行单机集群
docker run -it -d \
-p 6650:6650 \
-p 8080:8080 \
-v $PWD/data:/pulsar/data \
apachepulsar/pulsar:latest \
bin/pulsar standalone
docker 使用nats
先copy出nats的配置文件,然后再挂载,因为无法进入到容器内部
[root@rookieWRL myNats3]# ls
nats1-server.conf
[root@rookieWRL myNats3]# docker run -d -it -p 4222:4222 -v $PWD/nats1-server.conf:/nats-server.conf nats:latest
docker 使用postgres
docker run -d --name pg1 -p 5433:5432 -e POSTGRES_PASSWORD=wrl128201 -v D:/dockerVolumes/pg1:/var/lib/postgresql/data postgres
docker windows 运行kafka
你可以按照以下步骤在 Windows 上使用 Docker 运行 Kafka:
- 创建一个名为 docker-compose.yml 的文件,内容如下:
version: '3'
services:
zookeeper:
image: 'bitnami/zookeeper:latest'
ports:
- '2181:2181'
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: 'bitnami/kafka:latest'
ports:
- '9092:9092'
environment:
- KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092
depends_on:
- zookeeper
- 在 Docker Compose 中运行 Kafka:
docker-compose up -d
- 等待几分钟,直到 Kafka 启动完毕。可以使用以下命令检查 Kafka 是否启动成功:
docker-compose logs kafka | grep 'started (kafka\.server\.KafkaServer)'
如果看到类似于以下内容,说明 Kafka 启动成功:
kafka_1 | [2023-06-25 03:41:27,819] INFO [KafkaServer id=1] started (kafka.server.KafkaServer)
- 创建一个名为 test 的 Kafka 主题
docker exec -it kafka kafka-topics.sh --bootstrap-server localhost:9092 --create --partitions 1 --replication-factor 1 --topic test
- 启动一个控制台生产者
docker exec -it kafka kafka-console-producer.sh --broker-list localhost:9092 --topic test
- 启动一个控制台消费者,并从 test 主题开始消费消息
docker exec -it kafka kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning
docker 运行memgraph
docker run --name iec-memgraph -itd -p 7688:7687 -p 7445:7444 -p 3001:3000 memgraph/memgraph-platform
docker 部署mqtt(emqx)
docker run -d --name emqx -p 18083:18083 -p 1883:1883 -e emqx:latest
控制面板18083端口,新增一个账户
用户名:emqx_u
密码:EMQemq@1172
进入到emqx服务中
emqx ctl admins add emqx_u EMQemq@1172