Docker学习笔记
- 前言
- 一、Docker概述
- 二、Docker安装
- 三、Docker命令
- 四、Docker镜像
- 五、容器数据卷
- 六、DockerFile
- Docker命令小结
- 七、Docker网络原理
- 八、IDEA整合Docker
- 九、Docker Compose
- 十、Docker Swarm
- 十一、CI\CD Jenkins
前言
弱小和无知并非生存的障碍,傲慢才是。生活要常以谦卑的心态一、Docker概述
1.1 Docker为什么会出现?
首先,我们进行软件研发需要开发dev、线上prod两套环境,容易存在问题:
- 版本更新导致服务不可用
- 环境部署较麻烦(尤其是集群Redis、ES、Hadoop)
比如发布一个jar项目,但该jar的运行需要依赖Redis、ES、Hadoop等环境,也就是说部署该项目需要先安装以上几种环境,此时部署该项目就比较费时费力。如果能把这个项目与环境打包在一起部署,就会效率很多。
Docker给以上问题提供了解决方案,具体应用类似于打包Java程序为apk文件发布到应用商店,下次使用的时候在应用商店下载即可:
- Java程序 —— .apk —— 发布到应用商店 ------ 用户下载该.apk安装使用
- Java程序 —— 打包项目与环境为镜像(jar+依赖环境) —— 上传到Docker仓库 ------ 运维下载发布的镜像直接运行
其思想来自于集装箱,将项目与环境打包装箱,每个箱子是互相隔离的,Docker通过隔离机制,可以将服务器资源利用到极致。
1.2 Docker的历史
2010年,几个程序员在美国成立了一家名为dotCloud的公司,其旨在提供pass云计算服务(LXC有关的容器技术)。他们将自己的技术(容器化技术)命名为Docker,然而Docker刚刚诞生时并没有引起行业的关注。
2013年,dotCloud公司效益越发不景气,所以他们选择开源Docker技术。后来越来越多的人发现了Docker的优点,Docker火了,往后的每个月Docker都会更新一个新的版本。
2014年4月9日,Docker 1.0发布。
1.3 Docker为什么这么火爆?
简言:十分轻巧。在容器技术现世之前,我们使用的是虚拟机技术(VM),在windows中安装一个Vmware,通过这个软件我们可以虚拟出来一台或多台电脑,比较笨重。虚拟机属于虚拟化技术,Docker容器技术也属于虚拟化技术。
- VM,Linux Centos原生镜像(即一台电脑)隔离,需要开启多个虚拟机,占用几个G存储空间,耗时几分钟
- Docker,镜像机制(最核心的环境:JDK+MySQL+Redis,十分轻巧)隔离,直接运行即可,仅占用几十M存储空间,耗时为秒级别
Docker是基于Go语言开发的开源项目
官网地址:https://www.docker.com/
文档地址:https://docs.docker.com/
仓库地址:https://hub.docker.com/
1.4 虚拟机技术与容器化技术的区别
- 虚拟机技术:传统虚拟机虚拟出一个硬件,运行一个完整的操作系统,然后在这个系统上安装、运行软件。缺点:资源占用多、冗余步骤多、启动缓慢
- 容器化技术:并非模拟一个完整的操作系统,下图中的每一个小方块代表一个镜像。容器内的应用直接运行中在宿主机中,容器没有自己的内核,也没有虚拟硬件,所以很轻便。每个容器相互隔离,每个容器都有一个属于自己的文件系统,互不影响。
在DevOps(开发、运维)方面
- 更快的交付和部署
传统的部署:一堆帮助文档、安装程序
Docker部署:一键运行打包镜像、发布测试- 更便捷的升级和扩缩容
Docker部署应用像搭积木一样。比如一个项目使用了SpringBoot 1.5、Redis 5、Tomcat 8三种环境,其中Tomcat需要进行版本升级,Docker将其打包成镜像,现只需要升级该镜像并测试,后续的部署只需使用该镜像就可以了。服务器性能到瓶颈要水平扩展也更便捷- 更简单的系统运维
在容器化后,测试环境和线上环境高度一致- 更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上运行很多容器实例。服务器的性能可以发挥到极致
二、Docker安装
2.1 Docker的基本组成
镜像(image):Docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像 ==> run ==> tomcat01容器(提供服务)
容器(contianer):Docker利用容器技术独立运行一个或一组应用,容器是通过镜像来创建的。容器可以启动、停止、删除,都可以使用命令进行操作。目前可以把一个容器理解为是一个简易的Linux系统
仓库(repository):Docker仓库用来存放镜像,仓库分为公有仓库和私有仓库。DockerHub(默认是国外的)、阿里云等都有容器服务器(配置镜像加速)
2.2 Docker安装
环境准备:
[root@ziang ~]# uname -r # 查看系统内核版本
3.10.0-1127.19.1.el7.x86_64
[root@ziang ~]# 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
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 使用国内阿里云镜像仓库
# 更新yum软件包索引
yum makecache fast
# 4. 安装Docker引擎:docker引擎、docker客户端、守护进程containerd
yum install docker-ce docker-ce-cli containerd.io
# 5. 启动Docker
systemctl start docker
# 6. 查看Docker版本信息
docker version
# 7. Helloworld
docker run hello-world
# 8. 查看下载的hello-world镜像
docker images
# 9. (另)卸载Docker
yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker
Docker的默认工作路径(工作目录):/var/lib/docker
2.3 阿里云镜像加速
- 登录阿里云找到镜像容器
- 找到镜像加速
- 配置使用
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://f9ognzpb.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
2.4 docker run的执行流程
2.5 Docker工作原理
Docker是一个Client-Server架构的系统,Docker的守护进程运行在主机上,通过socket从客户端访问,docker-server接受到docker-client的指令就会执行
Docker为什么比VM快?
- Docker有着比虚拟机更少的抽象层
- Docker利用的是宿主机的内核,VM则需要Guest OS
由图可见,新建容器时Docker无需像虚拟机那样重新加载一个操作系统内核。虚拟机加载Guest OS耗时在分钟级别,而Docker利用宿主机省略了这个过程,耗时是秒级
三、Docker命令
帮助命令
docker version docker版本信息
docker info docker配置信息,包括镜像和容器数量
docker 命令 --help docker帮助命令,万能
官方帮助文档地址:https://docs.docker.com/engine/reference/run/
3.1 镜像命令
查看本地所有镜像:docker images
[root@ziang /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 4 months ago 13.3kB
rabbitmq management 246db2517862 8 months ago 186MB
# 列名解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的ID
CREATE 镜像的创建时间
SIZE 镜像的大小
# 可选项
--all , -a Show all images (default hides intermediate images)
--quiet , -q Only show image IDs
在镜像仓库中搜索镜像:docker search
[root@ziang ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 12047 [OK]
mariadb MariaDB Server is a high performing open sou… 4618 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 901 [OK]
# 可选项:通过搜索过滤
--filter=STARS=3000 # 搜索出来STARS大于3000的命令
在镜像仓库中下载镜像:docker pull
[root@ziang ~]# docker pull mysql
Using default tag: latest # 如果不指定tag,默认latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete # 分层下载,docker image的核心,联合文件系统
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址
# 以下两个命令等价
docker pull mysql
docker pull docker.io/library/mysql:latest
# 指定版本下载
[root@ziang ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists # 本地已存在的不再下载
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete # 仅下载缺少的
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
删除镜像:docker rmi
# 指定tag删除
[root@ziang ~]# docker rmi -f c20987f18b13
Untagged: mysql:5.7
Untagged: mysql@sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Deleted: sha256:c20987f18b130f9d144c9828df630417e2a9523148930dc3963e9d0dab302a76
Deleted: sha256:6567396b065ee734fb2dbb80c8923324a778426dfd01969f091f1ab2d52c7989
Deleted: sha256:0910f12649d514b471f1583a16f672ab67e3d29d9833a15dc2df50dd5536e40f
Deleted: sha256:6682af2fb40555c448b84711c7302d0f86fc716bbe9c7dc7dbd739ef9d757150
Deleted: sha256:5c062c3ac20f576d24454e74781511a5f96739f289edaadf2de934d06e910b92
# 删除多个镜像(后面跟多个tag即可)
[root@ziang ~]# docker rmi -f c20987f18b13 feb5d9fea6a5 246db2517862
# 删除所有镜像
[root@ziang ~]# docker rmi -f $(docker images -aq)
3.2 容器命令
说明:有了镜像才可以创建容器,所以需要先下载一个centos镜像:docker pull centos
新建容器并启动:docker run
docker run [可选参数] image
# 可选参数
--name="dockerName" 容器名,用来区分容器
-d 以后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器端口,可以将主机端口映射到容器端口,方式有如下几种
-p ip:80:8080 主机ip:主机端口:容器端口
-p 80:8080 主机端口:容器端口(常用)
-p 8080 容器端口
8080 容器端口
-P 随机指定端口
# 启动并进入容器
[root@ziang ~]# docker run -it centos /bin/bash # 使用交互式运行centos镜像,进入容器中查看内容。交互运行需要借助控制台,指定使用/bin/bash控制
[root@d034a3a4f9f3 /]# ls # 查看容器内,由于是基础版本,很多命令是不完善的
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@d034a3a4f9f3 /]# exit # 退出容器
exit
查看容器:docker ps
[root@ziang ~]# docker ps # 查看当前正在运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@ziang ~]# docker ps -a # 查看所有运行的容器(包括曾经运行过的容器)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d034a3a4f9f3 centos "/bin/bash" 9 hours ago Exited (0) 9 hours ago vibrant_lamport
8b6f1b616774 centos "/bin/bash" 9 hours ago Exited (0) 7 hours ago strange_nash
548b160ded84 feb5d9fea6a5 "/hello" 10 hours ago Exited (0) 10 hours ago optimistic_proskuriakova
483aa315754d 246db2517862 "docker-entrypoint.s…" 8 months ago Created rabbitmq
[root@ziang ~]# docker ps -a -n=1 # 查看最近运行的1个容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d034a3a4f9f3 centos "/bin/bash" 9 hours ago Exited (0) 9 hours ago vibrant_lamport
[root@ziang ~]# docker ps -aq # 查看所有运行的容器,-q仅显示容器id
d034a3a4f9f3
8b6f1b616774
548b160ded84
483aa315754d
退出容器:exit
exit # 停止容器并退出
Ctrl + P + Q # 不停止容器退出
删除容器:docker rm
docker rm 容器id # 删除指定容器id的容器,通过-f参数可删除正在运行的容器
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -a -a|xargs docker rm # 删除所有容器
启动和停止容器
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止运行中的容器
docker kill 容器id # 强制停止容器
[root@ziang ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@ziang ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d034a3a4f9f3 centos "/bin/bash" 9 hours ago Exited (0) 9 hours ago vibrant_lamport
[root@ziang ~]# docker start d034a3a4f9f3
d034a3a4f9f3
[root@ziang ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d034a3a4f9f3 centos "/bin/bash" 9 hours ago Up 3 seconds vibrant_lamport
[root@ziang ~]# docker stop d034a3a4f9f3
d034a3a4f9f3
[root@ziang ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docker容器的状态有:运行、停止。run启动容器进入运行状态,stop会让容器停止,rm会让容器消失(删除)
3.3 其他常用命令
后台启动容器
docker run -d 容器image
以该方式启动容器后,使用docker ps命令并没有发现启动的容器,也就是说该容器停止了。docker容器使用后台运行,需要有一个前台进程,docker发现没有前台应用就会自动停止。比如启动一个Nginx,容器启动后发现自己没有提供服务,就会立刻停止
查看容器日志:docker logs
docker logs [可选参数] 容器id
# 可选参数
-tf # 查看日志,t表示带有时间戳
--tail n # 显示最后n条日志
Demo:
[root@ziang ~]# docker run -d centos /bin/sh -c "while true;do echo ziang.zhang;sleep 1;done"
08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9
[root@ziang ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
08a4ec2e85f9 centos "/bin/sh -c 'while t…" 4 seconds ago Up 3 seconds cool_hodgkin
[root@ziang ~]# docker logs -tf --tail 10 08a4ec2e85f9
2022-02-03T01:19:31.160489316Z ziang.zhang
2022-02-03T01:19:32.162057672Z ziang.zhang
2022-02-03T01:19:33.163674626Z ziang.zhang
2022-02-03T01:19:34.165353081Z ziang.zhang
2022-02-03T01:19:35.167349305Z ziang.zhang
2022-02-03T01:19:36.169027025Z ziang.zhang
2022-02-03T01:19:37.170892402Z ziang.zhang
2022-02-03T01:19:38.172620267Z ziang.zhang
2022-02-03T01:19:39.174546190Z ziang.zhang
2022-02-03T01:19:40.176468912Z ziang.zhang
2022-02-03T01:19:41.178292254Z ziang.zhang
查看容器中的进程信息:docker top
docker top 容器id
[root@ziang ~]# docker top 08a4ec2e85f9
UID PID PPID C STIME TTY TIME CMD
root 4578 4558 0 09:18 ? 00:00:00 /bin/sh -c while true;do echo ziang.zhang;sleep 1;done
root 5181 4578 0 09:27 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看容器元数据:docker inspect
docker inspect 容器id
[root@ziang ~]# docker inspect 08a4ec2e85f9
[
{
"Id": "08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9",
"Created": "2022-02-03T01:18:56.873267955Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo ziang.zhang;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 4578,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-02-03T01:18:57.079480925Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"ResolvConfPath": "/var/lib/docker/containers/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9/hostname",
"HostsPath": "/var/lib/docker/containers/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9/hosts",
"LogPath": "/var/lib/docker/containers/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9-json.log",
"Name": "/cool_hodgkin",
"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/666f081c125b11f2c166ce349a8e6bce578d4720b1b76fdc6afd58b7c6993f43-init/diff:/var/lib/docker/overlay2/ab82fd3f5f7dfd160f732a74032059d85648202a69601a95239ef244ea6a4c3f/diff",
"MergedDir": "/var/lib/docker/overlay2/666f081c125b11f2c166ce349a8e6bce578d4720b1b76fdc6afd58b7c6993f43/merged",
"UpperDir": "/var/lib/docker/overlay2/666f081c125b11f2c166ce349a8e6bce578d4720b1b76fdc6afd58b7c6993f43/diff",
"WorkDir": "/var/lib/docker/overlay2/666f081c125b11f2c166ce349a8e6bce578d4720b1b76fdc6afd58b7c6993f43/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "08a4ec2e85f9",
"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 ziang.zhang;sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20210915",
"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": "b3eb26048d3703c07248154ca751b1c05e9cdcdced88e3df18da451914c555fd",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/b3eb26048d37",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "54ca19d0722608eb645ee47d5e07d482b2d5cfe6533591d3cc33e6912e5a14a4",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "7b73a049c8d1d281d8c66fe3dc1471696c813349d7e543123860c0f82c5aba97",
"EndpointID": "54ca19d0722608eb645ee47d5e07d482b2d5cfe6533591d3cc33e6912e5a14a4",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
进入正在运行的容器
我们通常使用后台方式运行容器,进入容器可以选择以下两种方式:
方式1:docker exec -it 容器id /bin/bash
(常用)
方式2:docker attach 容器id
前者进入容器会开启一个新的终端,后者进入容器正在执行的终端,不会开启新的终端
从容器内拷贝文件到主机
docker cp 容器id:容器路径 主机路径
3.4 小结
attach Attach to a running container # 当前shell下attach连接指定运行镜像
build Build an image from a Dockerfile # 通过Dockerfile定制镜像
commit Create a new image from a container changes # 提交当前容器为新的镜像
cp Copy files/folders from the containers filesystem to the host path # 从容器中拷贝指定文件或者目录到宿主机中
create Create a new container # 创建一个新容器,同run,但不启动容器
diff Inspect changes on a container # 查看docker容器变化
events Get real time events from the server # 从docker服务获取容器实时事件
exec Run a command in an existing container # 在已存在的容器上运行命令
export Stream the contents of a container as a tar archive # 导出容器的内容流作为一个tar归档文件[对应 import]
history Show the history of an image # 展示一个镜像形成历史
images List images # 列出系统当前镜像
import Create a new filesystem image from the contents of a tarball # 从tar包中的内容创建一个新的文件系统镜像[对应 export]
info Display system-wide information # 显示系统相关信息
inspect Return low-level information on a container # 查看容器详细信息
kill Kill a runing container # kill指定docker容器
load Load an image from a tar archive # 从一个tar包中加载一个镜像[对应 save]
login Register or Login to the docker registry server # 注册或登陆一个docker源服务器
logout Log out from a Docker registry server # 从当前Docker registry退出
logs Fetch the logs of a container # 输出当前容器日志信息
port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT # 查看映射端口对应的容器内部源端口
pause Pause all processes within a container # 暂停容器
ps List containers # 列出容器列表
pull Pull an image or a repository from the docker registry server # 从docker镜像源服务器拉取指定镜像或库镜像
push Push an image or repository to the docker registry server # 推送指定镜像或库镜像至docker源服务器
restart Restart a running container. # 重启运行的容器
rm Remove one or more container. # 移除一个或多个容器
rmi Remove one or more images # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需要先删除该容器或-f强制删除]
run Run a command in a new container. # 创建一个新的容器并运行一个命令
save Save an image to a tar archive. # 保存一个镜像为一个tar包[对应 load]
search Search for an image on the Docker Hub # 在docker hub中搜索镜像
start Start a stopped containers # 启动容器
stop Stop a running containers # 停止容器
tag Tag # 查看容器中运行的进程信息
unpause Unpause a paused container # 取消暂停容器
version Show the docker version informatioins # 查看docker版本号
wait Block until a container stops, then print its exit code # 截取容器停止时的推出状态值
3.5 练习使用Docker部署Nginx
[root@ziang ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
186b1aaa4aa6: Pull complete
b4df32aa5a72: Pull complete
a0bcbecc962e: Pull complete
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@ziang ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 5 weeks ago 141MB
centos latest 5d0da3dc9764 4 months ago 231MB
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
[root@ziang ~]# docker run -d --name nginx01 -p:3344:80 nginx
f7ff85d30a3099f60b88de8ec4db877ceed5a1b27722ccc5bee4b333cd7c3eb5
[root@ziang ~]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
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 and
working. 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>
端口暴露概念
3.5 可视化工具
- portainer(先用这个)
- rancher(CI/CD再用)
什么是portainer?
一个Docker图形化界面管理工具,提供可操作的后台面板。使用以下命令启动potainer:docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/potainer
通过浏览器http://ip:8088/访问,可以看到如下登陆界面:
进入之后就可以根据可视化面板控制
四、Docker镜像
4.1 镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。简单来说就是应用直接打包为docker镜像就可以运行起来。
如何得到镜像:
- 从远程仓库下载
- 朋友拷贝给你
- 自己制作一个镜像Dockerfile
4.2 Docker镜像加载原理
UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite serveral directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker镜像加载原理
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
dootfs(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、/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu、CentOS等等。
平时我们安装进虚拟机的CentOS大概几个G大小,但为什么Docker的镜像只有200M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版,rootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。
4.3 分层的理解
下载镜像观察打印的日志输出,可以看出镜像是一层一层下载的
[root@ziang ~]# docker pull redis
Using default tag: latest
latest: Pulling from library/redis
a2abf6c4d29d: Already exists
c7a4e4382001: Pull complete
4044b9ba67c9: Pull complete
c8388a79482f: Pull complete
413c8bb60be2: Pull complete
1abfd3011519: Pull complete
Digest: sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
理解:
所有的Docker镜像都起始于一个基础镜像,当进行修改或增加新的内容时,就会中当前镜像层上创建新的镜像层。
比如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
上图的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和Cow。
下图展示了与系统展示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
Docker镜像层都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层就是我们通常说的容器层,容器之下的都叫镜像层。我们的所有操作都是基于容器层的
4.4 commit镜像
docker commit # 提交容器成为一个新的副本
docker commit -m="commit note" -a="author" 容器id 目标镜像名:[TAG] # 命令和git类似
Demo:
# 1.启动一个tomcat容器
[root@ziang ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d7f032ea599 tomcat "catalina.sh run" 9 minutes ago Up 2 minutes 0.0.0.0:8080->8080/tcp nervous_maxwell
f7ff85d30a30 nginx "/docker-entrypoint.…" 7 days ago Up 7 days 0.0.0.0:3344->80/tcp nginx01
08a4ec2e85f9 centos "/bin/sh -c 'while t…" 7 days ago Up 7 days cool_hodgkin
[root@ziang ~]# docker exec -it 7d7f0 /bin/bash
root@7d7f032ea599:/usr/local/tomcat# ls webappps
# 2.tomcat官方镜像默认webapps目录下是空的,拷贝基本文件到webapps目录下
root@7d7f032ea599:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
root@7d7f032ea599:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@7d7f032ea599:/usr/local/tomcat# ls webapps
ROOT docs examples host-manager manager
# 3.将操作过的容器commit为一个镜像。以后可以使用该镜像启动容器
[root@ziang ~]# docker commit -a="ziang.zhang" -m="add some files to webapps" 7d7f03 tomcat.ziang.1.0
sha256:3418d38b10501944949f7230ad332d930e149a20294ee7f4e92d05b4ebd262e9
# 4.查看刚刚提交的镜像tomcat.ziang.1.0,发现它比tomcat大13MB,这就是cp操作后的结果
[root@ziang ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat.ziang.1.0 latest 3418d38b1050 9 seconds ago 693MB
nginx latest 605c77e624dd 6 weeks ago 141MB
tomcat latest fb5657adc892 7 weeks ago 680MB
redis latest 7614ae9453d1 7 weeks ago 113MB
centos latest 5d0da3dc9764 4 months ago 231MB
portainer/portainer latest 580c0e4e98b0 10 months ago 79.1MB
如果想保存容器的状态,就可以通过commit来提交,获得一个新镜像
学完以上命令,Docker学习才正式入门
五、容器数据卷
5.1 什么是容器数据卷
Docker将应用与环境打包成镜像,通过镜像启动容器。思考两个问题:
- 当启动一个mysql容器,在mysql中存储了大量数据,如果此时将该容器kill掉,那么容器中存储的数据将会丢失
- 当需要频繁修改容器中的配置文件时,每次都需要进入该容器进行修改,会比较麻烦
所以Docker应该有一个持久化和同步数据的机制,将容器中产生的数据同步到本地,这个机制就是容器数据卷,将容器内的目录挂在到本地目录
使用容器数据卷技术,可以将主机目录与容器内目录进行挂载,在其中一个目录更新了内容,另一个目录就会进行同步更新。另外,只要该容器存在,无论启动与否,数据的同步仍在进行。如果该容器被rm,那么数据将依然存在,但同步将不再
总结:容器数据卷是容器数据的持久化和同步技术,各个容器之间也可以使用该技术。
5.2 容器数据卷使用方式一:-v 参数
方式一:启动容器时使用-v参数
docker run -it -v 主机目录1:容器目录1 -v 主机目录2:容器目录2 ...
实战:安装MySQL并使用容器数据卷
1.docker pull mysql:5.7
# 参数
-d 后台启动
-p 端口暴露
-v 数据卷挂载
-e 环境变量配置
--name 容器命名
2.docker run -d -p 3306: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
3.启动成功后,使用MySQL图形界面连接到服务器的3306端口,创建一个数据库并在其中创建表进行插入操作
4.去服务器/home/mysql/data目录下查看是否创建了该目录(数据库)与文件(表)
宿主机的挂载目录与容器中的挂载目录不存在时都会自动创建
5.3 具名挂载与匿名挂载
# 匿名挂载:-v 容器目录(仅指定容器目录)
[root@ziang ~]# docker run -d -P -v /etc/nginx --name nginx02 nginx # -P 随机指定端口
61dacb811c228b36fea583509bd303dcc2c22647631e6cfe2ca780c353bb29ef
# 查看所有容器数据卷情况,每一条数据代表一个真实存在的目录
[root@ziang ~]# docker volume ls
DRIVER VOLUME NAME
local 26cd6fb4a595803c408f4b43f2fb97ca46df35a2ca6634ee3dded63a5b7ed235
local 922e29647b7fcc546841088a0e9580e79c849cd669096ce306cd2c74b4d464a0
local 62326bf1e0e8601ca8e2f0961d54deae6de13d05a605b1a242551592a1a36236
local d7331eebf78e6fe7e5793efc256a3dacec290d698c28fd6eabc98a0a06b6176d
local e5300d1e74f17909816fc94b1445e7e686d27283fff2047d7128026392dad324
# 具名挂载:-v 卷名/容器目录
[root@ziang ~]# docker run -d -P -v juming-nginx:/etc/nginx --name nginx03 nginx
59d2cc2ba71fb03c01a7beb42ced116345498ecf25a60c43a411ec395aeb3dd8
[root@ziang ~]# docker volume ls
DRIVER VOLUME NAME
local 26cd6fb4a595803c408f4b43f2fb97ca46df35a2ca6634ee3dded63a5b7ed235
local 922e29647b7fcc546841088a0e9580e79c849cd669096ce306cd2c74b4d464a0
local 62326bf1e0e8601ca8e2f0961d54deae6de13d05a605b1a242551592a1a36236
local d7331eebf78e6fe7e5793efc256a3dacec290d698c28fd6eabc98a0a06b6176d
local e5300d1e74f17909816fc94b1445e7e686d27283fff2047d7128026392dad324
local juming-nginx
# 查看目录位置(在没有指定目录的情况下,所有挂载的目录都在/var/lib/docker/volumes/下)
[root@ziang ~]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2022-02-15T23:20:50+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
通过具名挂载可以方便地找到该卷,多数情况下使用具名挂载
如何确认使用何种方式挂载?
- 指定路径挂载:-v 主机路径:容器路径
- 匿名挂载:-v 容器内路径
- 具名挂载:-v 卷名:容器路径
拓展:
# -v 容器内路径:ro
ro readonly 只读,数据只能在外部改变,容器内部只能读数据
docker run -d -P -v juming-nginx:/etc/nginx:ro --name nginx03 nginx
# -v 容器内路径:rw
rw readrwrite 可写,数据可以在外部改变,也可以在内部改变
docker run -d -P -v juming-nginx:/etc/nginx:rw --name nginx03 nginx
# 一旦设置了该权限,挂载出来的内容就会存在限定。
# 只要看到ro,就说明该目录内容只能由宿主机来操作,容器内部无法操作
5.4 容器数据卷使用方式二:Dockerfile
DockerFile是用来构建docker镜像的文件,内容是命令脚本,可以通过它生成镜像。
镜像是一层一层的结构,而DockerFile的每一行命令就对应其中一层
[root@ziang containerDataVolume]# vim dockerfile1
[root@ziang containerDataVolume]# cat dockerfile1
FROM centos # 使用基础镜像
VOLUME ["volume01","volume02"] # 挂载数据卷(匿名挂载)
CMD echo "----- end -----" # 执行
CMD /bin/bash
# -f dockerfile路径;-t 镜像名
[root@ziang containerDataVolume]# docker build -f dockerfile1 -t ziangTest/centos .
Sending build context to Docker daemon 4.608kB
Step 1/4 : FROM centos
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 914d32002e92
Removing intermediate container 914d32002e92
---> a45fc8e2da0a
Step 3/4 : CMD echo "----- end -----"
---> Running in d574aa3ce16b
Removing intermediate container d574aa3ce16b
---> cff2dd066931
Step 4/4 : CMD /bin/bash
---> Running in e44806b5d641
Removing intermediate container e44806b5d641
---> e3771927547f
Successfully built e3771927547f
Successfully tagged ziangTest/centos:latest
[root@ziang containerDataVolume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ziangTest/centos latest e3771927547f 4 minutes ago 231MB
tomcat.ziang.1.0 latest 3418d38b1050 5 days ago 693MB
nginx latest 605c77e624dd 6 weeks ago 141MB
tomcat latest fb5657adc892 7 weeks ago 680MB
redis latest 7614ae9453d1 8 weeks ago 113MB
mysql latest 3218b38490ce 8 weeks ago 516MB
centos latest 5d0da3dc9764 5 months ago 231MB
portainer/portainer latest 580c0e4e98b0 11 months ago 79.1MB
[root@ziang ~]# docker run -it ziangTest/centos /bin/bash
[root@547072811dc7 /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Feb 16 13:28 dev
drwxr-xr-x 1 root root 4096 Feb 16 13:28 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 14:17 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 110 root root 0 Feb 16 13:28 proc
dr-xr-x--- 2 root root 4096 Sep 15 14:17 root
drwxr-xr-x 11 root root 4096 Sep 15 14:17 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Feb 16 13:28 sys
drwxrwxrwt 7 root root 4096 Sep 15 14:17 tmp
drwxr-xr-x 12 root root 4096 Sep 15 14:17 usr
drwxr-xr-x 20 root root 4096 Sep 15 14:17 var
drwxr-xr-x 2 root root 4096 Feb 16 13:28 volume01 # 挂载目录1
drwxr-xr-x 2 root root 4096 Feb 16 13:28 volume02 # 挂载目录2
[root@73216b2be2dd volume01]# exit
exit
[root@ziang ~]# docker inspect 73216b2be2dd
# 在Mounts中可看到该容器的数据卷挂载信息
这种方式比较常见,可以在构建自己的镜像时进行卷挂载;若没有中构建镜像时挂载,则可以在启动容器的时候使用-v参数进行挂载
5.5 数据卷容器
Demo:
[root@ziang ~]# docker run -it --name dockerA ziang/centos
[root@ziang ~]# docker run -it --name dockerB --volumes-from dockerA ziang/centos
[root@ziang ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f406eff2f33c ziang/centos "/bin/sh -c /bin/bash" 39 seconds ago Up 38 seconds dockerB
671c33eb072f ziang/centos "/bin/sh -c /bin/bash" About a minute ago Up About a minute dockerA
[root@ziang ~]# docker attach 671c33eb072f
[root@671c33eb072f /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
[root@671c33eb072f /]# cd volume01
[root@671c33eb072f volume01]# touch abc.java
[root@671c33eb072f volume01]# read escape sequence # ctrl + p + q
[root@ziang ~]# docker attach f406eff2f33c
[root@f406eff2f33c /]# cd volume01
[root@f406eff2f33c volume01]# ls
abc.java # dockerA创建的文件同步到了dockerB,相当于A被B继承,A就是数据卷容器
[root@ziang ~]# docker run -it --name dockerC --volumes-from dockerA ziang/centos
[root@aaf87d82d739 /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
[root@aaf87d82d739 /]# cd volume01
[root@aaf87d82d739 volume01]# ls
abc.java # 再创建一个dockerC同步挂载dockerA,该文件也存在
[root@ziang ~]# docker rm -f 671c33eb072f
671c33eb072f
[root@ziang ~]# docker attch f406eff2f33c
docker: 'attch' is not a docker command.
See 'docker --help'
[root@ziang ~]# docker attach f406eff2f33c
[root@f406eff2f33c volume01]# ls
abc.java # 删除dockerA,其他容器仍存在该文件
对多个MySQL容器进行数据同步
[root@ziang ~]# docker run -d -p 3345:3306 --name mysqlA -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
[root@ziang ~]# docker run -d -p 3346:3306 --name mysqlB -e MYSQL_ROOT_PASSWORD=123456 --volumes-from mysqlA mysql:5.7
总结:可以实现容器间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止
六、DockerFile
6.1 DockerFile介绍
Dockerfile是用来构建Docker镜像的文件,一个命令参数脚本
构建步骤:
- 编写一个Dockerfile文件
- docker build 构建为一个镜像
- docker run 运行镜像
- docker push 发布到DockerHub或阿里云镜像仓库
很多官方镜像都是基础包,很多功能没有,需要用户按需求搭建自己的镜像
6.2 DockerFile构建过程
基础知识:
- 关键字指令单词是大写的
- 执行顺序自上而下
- ‘#’ 表示注释
- 每条指令都会创建一个新的镜像层并提交
DockerFile是面向开发的,以后要发布项目做镜像,就需要编写DockerFile文件,这个文件十分简单
Docker镜像逐渐成为企业交付的标准
- DockerFile:构建文件,定义了一切的步骤,源代码
- DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品
- DockerContainer:容器是由镜像运行起来提供服务的
6.3 DockerFile命令
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是由谁编写的,姓名+邮箱
RUN # 镜像构建时需要运行的命令
ADD # 构建步骤,比如搭建一个tomcat镜像,需要加入一个tomcat的压缩包,即添加内容
WORKDIR # 镜像的工作目录
VOLUME # 设置容器卷,挂载的目录
EXPOSE # 暴露端口,写了该参数就不需要在run -p中指定端口
CMD # 指定该容器启动时(docker run)要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定该容器启动时(docker run)要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承的DockerFile,这个时候会运行 ONBUILD的指令(触发指令)
COPY # 类似ADD,将文件拷贝到镜像中
ENV # 构建时设置环境变量
6.4 实战测试
DockerHub中99%的镜像都是从基础镜像scratch开始的,然后添加需要的配置和软件进行构建
Demo:
# 1.编写Dockerfile文件
[root@ziang dockerfile]# cat dockerfile-mycentoscat dockerfile-mycentos
FROM centos # 从centos开始构建
MAINTAINER ziangzhang<tzuaness@gmail.com> # 构建人信息
ENV MYPATH /use/local # 设置环境变量
WORKDIR $MYPATH # 工作目录(一进入镜像就会首先在工作目录)
RUN yum -y install vim # 下载vim
RUN yum -y install net-tools # 下载net-tools
EXPOSE 80 # 暴露端口
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
# 2.通过文件构建镜像
# docker build -f dockerfile文件路径 -t 镜像名:版本号
[root@ziang dockerfile]# cat dockerfile-mycentosdocker build -f dockerfile-mycentos -t mycentos:0.1 .
列出镜像的变更历史:docker history 镜像id/镜像名
6.4 CMD与ENTRYPOINT的区别
CMD # 指定该容器启动时(docker run)要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定该容器启动时(docker run)要运行的命令,可以追加命令
Demo:
# CMD
[root@ziang dockerfile]# cat dockerfile-cmd-test
FROM tomcat
CMD ["ls","-a"]
[root@ziang dockerfile]# docker build -f dockerfile-cmd-test -t dockerfile-cmd:0.1 .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM tomcat
---> fb5657adc892
Step 2/2 : CMD ["ls","-a"]
---> Using cache
---> 9e26f3ba0a87
Successfully built 9e26f3ba0a87
Successfully tagged dockerfile-cmd:0.1
[root@ziang dockerfile]# docker run dockerfile-cmd:0.1
.
..
BUILDING.txt
CONTRIBUTING.md
LICENSE
NOTICE
README.md
RELEASE-NOTES
RUNNING.txt
bin
conf
lib
logs
native-jni-lib
temp
webapps
webapps.dist
work
# 想在运行该容器时追加一个命令-l想达到ls -al的效果,但在CMD下-l替换了CMD ["ls","-a"],-l并非命令,所以报错
[root@ziang dockerfile]# docker run dockerfile-cmd:0.1 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
# ENTRYPOINT
[root@ziang dockerfile]# cat dockerfile-entrypoint-test
FROM tomcat
ENTRYPOINT ["ls","-a"]
[root@ziang dockerfile]# docker build -f dockerfile-entrypoint-test -t dockerfile-entrypoint:0.1 .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM tomcat
---> fb5657adc892
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in 43fa27dc91b0
Removing intermediate container 43fa27dc91b0
---> e95e71dd650b
Successfully built e95e71dd650b
Successfully tagged dockerfile-entrypoint:0.1
[root@ziang dockerfile]# docker run dockerfile-entrypoint:0.1
.
..
BUILDING.txt
CONTRIBUTING.md
LICENSE
NOTICE
README.md
RELEASE-NOTES
RUNNING.txt
bin
conf
lib
logs
native-jni-lib
temp
webapps
webapps.dist
work
[root@ziang dockerfile]# docker run dockerfile-entrypoint:0.1 -l
total 168
drwxr-xr-x 1 root root 4096 Dec 22 17:07 .
drwxr-xr-x 1 root root 4096 Dec 22 17:00 ..
-rw-r--r-- 1 root root 18994 Dec 2 22:01 BUILDING.txt
-rw-r--r-- 1 root root 6210 Dec 2 22:01 CONTRIBUTING.md
-rw-r--r-- 1 root root 60269 Dec 2 22:01 LICENSE
-rw-r--r-- 1 root root 2333 Dec 2 22:01 NOTICE
-rw-r--r-- 1 root root 3378 Dec 2 22:01 README.md
-rw-r--r-- 1 root root 6905 Dec 2 22:01 RELEASE-NOTES
-rw-r--r-- 1 root root 16517 Dec 2 22:01 RUNNING.txt
drwxr-xr-x 2 root root 4096 Dec 22 17:07 bin
drwxr-xr-x 2 root root 4096 Dec 2 22:01 conf
drwxr-xr-x 2 root root 4096 Dec 22 17:06 lib
drwxrwxrwx 2 root root 4096 Dec 2 22:01 logs
drwxr-xr-x 2 root root 4096 Dec 22 17:07 native-jni-lib
drwxrwxrwx 2 root root 4096 Dec 22 17:06 temp
drwxr-xr-x 2 root root 4096 Dec 22 17:06 webapps
drwxr-xr-x 7 root root 4096 Dec 2 22:01 webapps.dist
drwxrwxrwx 2 root root 4096 Dec 2 22:01 work
6.5 实战:制作Tomcat镜像
1 准备镜像文件:Tomcat压缩包,JDK压缩包
2 编写Dockerfile,官方命名即Dockerfile
,docker build会自动寻找该命名的文件,无需再通过-f参数指定
FROM centos
MAINTAINER ziang.zhang<tzuaness@gmail.com>
COPY readme.txt /usr/local/readme.txt
ADD apache-tomcat-9.0.33.tar.gz /usr/local/
ADD jdk-8u65-linux-x64.rpm /usr/local/
RUN yum -y install vim
ENV MYWORKPATH /usr/local
ENV JAVA_HOME /usr/local/jdk1.8.0_65
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/toos.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.33
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.33
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
WORKDIR $MYWORKPATH
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.33/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.33/bin/logs/catalina.out
[root@ziang zhangziang]# ls
apache-tomcat-9.0.33.tar.gz readme.txt
Dockerfile redis-6.0.6.tar.gz
jdk-8u65-linux-x64.rpm
[root@ziang zhangziang]# vim Dockerfile
[root@ziang zhangziang]# cat Dockerfile
FROM centos
MAINTAINER ziang.zhang<tzuaness@gmail.com>
COPY readme.txt /usr/local/readme.txt
COPY jdk-8u65-linux-x64.rpm /usr/local/
ADD apache-tomcat-9.0.33.tar.gz /usr/local/
RUN yum -y install vim
RUN rpm -ivh /usr/local/jdk-8u65-linux-x64.rpm
ENV MYWORKPATH /usr/local
ENV JAVA_HOME /usr/java/jdk1.8.0_65
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/toos.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.33
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.33
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
WORKDIR $MYWORKPATH
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.33/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.33/bin/logs/catalina.out
[root@ziang zhangziang]# docker build -t zomcat:0.1 .
[root@ziang zhangziang]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
zomcat 0.1 49635e747d1d 2 minutes ago 407MB
# 挂载数据卷时,宿主机与容器中没有的目录会自动创建。挂载webapps目录后,发布的项目可以直接放置在本地
[root@ziang zhangziang]# docker run -d -p 9090:8080 --name ziangtomcat -v /home/zhangziang/tomcat/webapps:/usr/local/apache-tomcat-9.0.33/webapps/test -v /home/zhangziang/tomcat/logs:/usr/local/apache-tomcat-9.0.33/logs zomcat:0.1
6.6 发布自己的镜像
发布到DockerHub
- 前往DockerHubhttps://hub.docker.com/,注册自己的账号
- 使用
docker login
命令进行登陆 - 使用
docker push
命令将自己的镜像发布到DockerHub中
发布到阿里云镜像仓库
- 登陆阿里云找到容器镜像服务
- 创建命名空间和镜像仓库
- 进入镜像仓库可查看使用步骤
相关命令:
$ docker login --username=tz**** registry.cn-hangzhou.aliyuncs.com
$ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/ziang_repository/demo01:[镜像版本号]
$ docker push registry.cn-hangzhou.aliyuncs.com/ziang_repository/demo01:[镜像版本号]
$ docker pull registry.cn-hangzhou.aliyuncs.com/ziang_repository/demo01:[镜像版本号]
Docker命令小结
七、Docker网络原理
7.1 理解Docker0
三个网络分别代表三种环境,那么Docker是如何处理容器网络访问的?