【docker】学习笔记

学习来源

【狂神说Java】Docker最新超详细版教程通俗易懂

概述

传统的开发:后端提供jar包,运维搭建环境,然后运行jar包,但是中间会产生很多问题
基于docker的开发:后端打包的时候带上环境得到一个镜像,将镜像上传到Docker仓库,运维下载我们发布的镜像,直接运行就好了。

以往实现隔离的一个方法是虚拟机,如vm软件,通过它可以虚拟出一台或者多台电脑,但是它虚拟出来的就是非常完全的电脑了,很大,很笨重,启动很缓慢,并且必须要安装vm软件,而这个软件也很大。
现在实现隔离可以使用docker,它不采用虚拟机而是采用镜像(核心思想和虚拟机一样),但是镜像中只包含一台电脑最核心的部分以及我们自己得到一些东西,所以很小,很轻便,启动很迅速,并且只需要配置docker环境就好了,很方便。

虚拟机:资源占用多;冗余步骤多;启动速度慢。因为它虚拟出一套硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件。
在这里插入图片描述

docker:容器中的应用运行在宿主机上,容器没有自己的内核,也没有虚拟我们的硬件(直接使用宿主机的操作系统),所以就轻便了。并且每个容器相互隔离,每个容器内都有一个属于自己的文件系统,互不影响。
在这里插入图片描述
应用更快速的交付与部署
传统:需要一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行

更便捷的升级和扩缩容
部署应用就和搭积木一样
只需要拓展容器
更便捷的系统运维:开发和测试环境高度一致
更高效的计算资源利用:Docker是内核级的虚拟化,一个物理机上可以运行很多的容器实例

基于docker的开发流程:

书写dockerfile,定义一切的步骤
通过dockerfile构建生成镜像,最终发布和运行这个镜像
进行运行起来得到容器,提供服务

Docler安装

相关名词解释

在这里插入图片描述

总体概述:docker的服务启动之后,我们可以通过客户端的命令使用,比如运行。这个运行是发生在docker的服务上的,通过镜像创建容器实例,而镜像是来自于远程仓库的。
镜像(image):镜像就像是类,可以通过这个类创建容器实例,如通过tomcta镜像创建tomcat01容器,tomcat02容器…也就是说,一个镜像可以创建多个容器(最终服务或者项目运行在容器中)
容器(container):Docker利用容器技术,独立运行一个或者一组应用,容器通过镜像创建。包含一些简单的命令(如启动、停止、删除等),可以将容器理解为一个简易的linux系统
仓库(repository):仓库就是存放镜像的地方,分为共有仓库和私有仓库,默认是docker hub(国外的),我们可以使用国内的镜像加速。

安装与原理

安装参考Ubuntu安装docker

PS:除了5.安装一直不行,后发现链接中的方法一,尝试之后解决了。但是有一点点奇怪,5.安装中需要安装的是docker-ce docker-ce-cli containerd.io三部分,而采用链接中的方法一,我只是安装了docker-ce一部分。讲道理应该会出点什么问题,没想到后面运行起来一点问题都没有,我也就没在意了。

docker的默认工作路径:/var/lib/docker

docker run的原理图
在这里插入图片描述
Docker的工作原理: Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问,Server接收到Client的指令,就会执行这个指令。
在这里插入图片描述

阿里云docker镜像加速

阿里云->控制台->打开左边菜单出窗口,搜索容器镜像服务->镜像工具->镜像加速器->按照操作文档进行(总共四步)

Ubuntu环境下docker每次都需要sudo的问题

参考链接:解决Docker必须使用sudo操作的问题

问题原因:Docker守候进程绑定的是一个unix socket,而不是TCP端口。这个套接字默认的属主是root,其他是用户可以使用sudo命令来访问这个套接字文件。因为这个原因,docker服务进程都是以root帐号的身份运行的。为了避免每次运行docker命令的时候都需要输入sudo,可以创建一个docker用户组,并把相应的用户添加到这个分组里面。当docker进程启动的时候,会设置该套接字可以被docker这个分组的用户读写。这样只要是在docker这个组里面的用户就可以直接执行docker命令了。
做法:

sudo groupadd docker # 创建docker用户组,我这不用创建,因为自带了的
sudo gpasswd -a yxx docker # 将当前用户添加刀docker用户组下
newgrp docker #更新docker用户组
sudo service docker restart # 重启docker的服务

docker常用命令

万能命令:

docker version # 显示docker的版本信息
docker info #显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help 

镜像命令

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

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              feb5d9fea6a5        13 months ago       13.3kB

# 解释
REPOSITORY 镜像的仓库源
TAG 仓库的标签
IIMAGE ID 镜像的ID
CREATED 镜像创建时间
SIZE 镜像的大小

# 可选项
-a 列出所有镜像 -q 只显示镜像ID

docker search:搜索镜像

如:docker search mysql
# 可选项
-s 3000 #搜索stars数超过3000的

docker pull:拉取镜像

docker pull mysql  #下载最新版本的
# 这个版本需要Docker Hub中有,也就是得从Docker Hub中复制
docker pull mysql:5.7 #下载指定版本

在这里插入图片描述

删除镜像

docker rmi
# 可选项
-f # 强制删除
# 删除单个
docker rmi 镜像id
# 删除多个
docker rmi 镜像id1,镜像id2...
# 删除全部
docker rmi -f $(docker images -aq)

容器命令

新建容器并启动

docker run [可选参数] image
# 参数说明
--name #容器名字,用于区分容器
-d #后台运行
-it #使用交互方式云兄,进入容器查看内容
-P #指定容器端口 -p 8080:8080 将容器的8080和宿主机的8080映射起来
	-p #ip:主机端口:容器端口
	-p #主机端口:容器端口(最常用)
	-p #容器端口
	#直接容器端口
-p #随机指定端口
-v # 卷挂载
-e # 环境配置

# 注:runm命令书写完毕之后,后面可以追加一些linux命令,会在容器创建的时候顺便执行,如ls

例子:

# 下载centos镜像
sudo docker pull centos

# 运行docker镜像
docker run -it centos /bin/bash

# 观察发现:主机名从宿主机的名字变为了容器的ID了
yxx@yxx-virtual-machine:~$ sudo docker run -it centos /bin/bash
# 容器内部的centos貌似和正常的服务器一样,但只是一个基本版本,很多命令都是不完善的。
[root@24b1e75ad64b /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
# 使用exit命令离开容器
[root@24b1e75ad64b /]# exit
exit
yxx@yxx-virtual-machine:~$

列出所有运行中的容器

docker ps
# 参数说明
-a #列出所有运行中的容器+历史运行过的
-n=? #显示最近创建的n个容器
-q #只显示容器的编号

yxx@yxx-virtual-machine:~$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
yxx@yxx-virtual-machine:~$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
24b1e75ad64b        centos              "/bin/bash"         9 minutes ago       Exited (0) 4 minutes ago                       peaceful_galileo
bfaf1242b997        hello-world         "/hello"            10 hours ago        Exited (0) 10 hours ago                        frosty_swanson
yxx@yxx-virtual-machine:~$ sudo docker ps -a -n=1
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
24b1e75ad64b        centos              "/bin/bash"         9 minutes ago       Exited (0) 5 minutes ago                       peaceful_galileo
yxx@yxx-virtual-machine:~$ sudo docker ps -aq
24b1e75ad64b
bfaf1242b997

退出容器

exit # 停止容器退出
ctrl +p+q # 不停止容器退出
# 注:第二种方式可能会和IDE的快捷键重复,需要修改IDE的快捷键

删除容器(类似于删除镜像)

docker rm
# 可选项
-f # 强制删除,比如正在运行的容器就需要强制删除
# 删除单个
docker rm 镜像id
# 删除多个
docker rm 镜像id1,镜像id2...
# 删除全部
docker rm -f $(docker ps-aq)

启动和停止容器的操作

docker start 容器id # 启动容器,这里是启动已有容器,和上面的docker run不一样哟
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前运行的容器

其他命令

后台启动容器

docker run -d centos

# 问题:docker ps发现centos停止了
# 原因:docker 容器使用后后台运行,就必须要有一个前台进程,否则就会自动停止

查看日志

docker logs 容器id

# 可选项
-f # 跟踪日志输出,相当于实时显示
-t # 显示时间戳
--tail #num 实现最后的num行

查看容器内的进程信息

docker top 容器id

yxx@yxx-virtual-machine:~$ docker top 01a9965e48a7
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                8163                8129                0                   09:41               pts/0               00:00:00            /bin/bash

查看容器源数据

docker inspect 容器id

yxx@yxx-virtual-machine:~$ docker inspect 01a9965e48a7
[
    {
        "Id": "01a9965e48a7fdc8187dafaecf5c4c860d27a15d19f0791e5ebe41526b9ae747",
        "Created": "2022-11-01T01:41:02.7790332Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 8163,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-11-01T01:41:03.452265438Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/01a9965e48a7fdc8187dafaecf5c4c860d27a15d19f0791e5ebe41526b9ae747/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/01a9965e48a7fdc8187dafaecf5c4c860d27a15d19f0791e5ebe41526b9ae747/hostname",
        "HostsPath": "/var/lib/docker/containers/01a9965e48a7fdc8187dafaecf5c4c860d27a15d19f0791e5ebe41526b9ae747/hosts",
        "LogPath": "/var/lib/docker/containers/01a9965e48a7fdc8187dafaecf5c4c860d27a15d19f0791e5ebe41526b9ae747/01a9965e48a7fdc8187dafaecf5c4c860d27a15d19f0791e5ebe41526b9ae747-json.log",
        "Name": "/objective_lichterman",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "docker-default",
        "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,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "shareable",
            "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,
            "DiskQuota": 0,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": 0,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/asound",
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/bd0c9478212f552bf44aeddcb8733e823aeb62bb5f4fb23a1f54fc47419d5548-init/diff:/var/lib/docker/overlay2/0c3a069df4f2f44e3b7a688fba2da1725763adbfcb748ee3b3b145d268f90df2/diff",
                "MergedDir": "/var/lib/docker/overlay2/bd0c9478212f552bf44aeddcb8733e823aeb62bb5f4fb23a1f54fc47419d5548/merged",
                "UpperDir": "/var/lib/docker/overlay2/bd0c9478212f552bf44aeddcb8733e823aeb62bb5f4fb23a1f54fc47419d5548/diff",
                "WorkDir": "/var/lib/docker/overlay2/bd0c9478212f552bf44aeddcb8733e823aeb62bb5f4fb23a1f54fc47419d5548/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "01a9965e48a7",
            "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": "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": "df26a97791bb78e8aa362832ebbc7c7614674c2c40c5ebcb2d5084d8bd5bfbdc",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/df26a97791bb",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "6ba4c63ca046439524103eee1341ba054887624c4e89e51b93041ad45d620970",
            "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": "6924a1633bcaff3d8d9e6d83686123fae0c6865e1aaea7e15f64f0d18c9c4f19",
                    "EndpointID": "6ba4c63ca046439524103eee1341ba054887624c4e89e51b93041ad45d620970",
                    "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
                }
            }
        }
    }
]

进入当前正在运行的容器(因为我们通畅都是后台运行容器的,需要进入容器,修改一些配置)

docker exec -it 容器id bashShell # 进入容器后,打开一个新的终端
docker attach  容器id # 进入容器后,进入正在执行的终端

yxx@yxx-virtual-machine:~$ docker exec -it 01a9965e48a7 /bin/bash
[root@01a9965e48a7 /]# 

yxx@yxx-virtual-machine:~$ docker attach  01a9965e48a7
[root@01a9965e48a7 /]#

从容器内拷贝文件到主机上(手动操作,后期可以实现容器内目录和主机目录的同步)

docker cp 容器id:文件原路径 主机内路径

# 容器中创建文件
[root@2c4f97b54e8e /]# touch /home/1.java
# 退出容器后通过cp命令拷贝到主机中
yxx@yxx-virtual-machine:~/yxx$ docker cp 2c4f97b54e8e:/home/1.java /home/yxx/test/
yxx@yxx-virtual-machine:~/yxx$ ls /home/yxx/test/
1.java

汇总

在这里插入图片描述

attach	#当前 shell 下 attach 连接指定运行镜像
build	#通过 Dockerfile 定制镜像
commit	#提交当前容器为新的镜像
cp	#容器中拷贝指定文件或者目录到宿主机中
create	# 创建一个新的容器,同 run,但不启动容器
diff		#查看docker 容器变化
events	#从 docker 服务获取容器实时事件
exec	#在已存在的容器上运行命令
export	#导出容器的内容流作为一个 tar 归档文件[对应 import ]
history	#展示一个镜像形成历史
images	#列出系统当前镜像
import	#从tar包中的内容创建一个新的文件系统映像[对应export]
info	#显示系统相关信息
inspect	#查看容器详细信息
kill	#kill 指定 docker 容器
load	#从一个 tar 包中加载一个镜像[对应 save]
login	#注册或者登陆一个 docker 源服务器
logout	#从当前 Docker registry 退出
logs	#输出当前容器日志信息
port	#查看映射端口对应的容器内部源端口
pause	#暂停容器
ps		#列出容器列表

练习(docker安装Nginx)

docker search nginx
docker pull nginx
docker run -d --name nginx01 -p 3344:80 nginx
curl localhost:3344 # 本机测试能否访问nginx,当然可以外网直接访问,但是需要开发本机的3344端口
docker exec -it 41d6fc1059b8 /bin/bash 
docker exec -it nginx01 /bin/bash # 通过name或者容器id都可以实现进入容器,但是最好不要用attach命令,因为不方便啊

端口暴露的解释:
在这里插入图片描述

可视化

portainer(用的很少)->Rancher(持续集成、持续部署的时候使用,企业用的很多)

# 前面其实就是之前学习的命令 中间的-v开始是挂载命令 最后一部分是运行portainer
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

portainer用处:Docker的图形化管理界面!提供后台面板,但是一般不用
访问:localhost:8088
在这里插入图片描述

容器数据卷

需求:数据持久化,就是容器删了,但是数据不丢;Mysql数据存储在本地
容器数据卷:容器的持久化与同步操作,并且支持容器间的数据共享!Docker容器中产生的数据,同步到本地。其实回过头来看看,数据卷就是容器和主机交互的桥梁,中间存在类似指针的概念,数据就是存在主机中的,通过容器卷可以访问、操作主机中的目录,所以删除容器不会删除卷中的数据。

容器与主机的数据交互

后面两种方式的区别就是,卷是放在用户指定的位置还是docker指定的位置,如果放在docker指定的位置下的话(第二种方式的话),卷名是docker指定的还是自己设定的。

方式1:目录映射:直接使用命令挂载 -v(可以有多个)

docker run -it -v 主机目录:容器内目录 -v 主机目录:容器内目录  # 注:主机目录是通过/开始的,也就是绝对路径

# 将容器内的/home目录与主机的/home/yxx/centos-test目录绑定
# 在容器内的/home目录下放入 1java文件
yxx@yxx-virtual-machine:~$ docker run -it -v /home/yxx/centos-test:/home  centos /bin/bash
[root@04cdceaf7d88 /]# cd home/
[root@04cdceaf7d88 home]# touch 1.java
[root@04cdceaf7d88 home]# ls
1.java

# 回来主机,检查是否挂载成功
yxx@yxx-virtual-machine:~$ docker inspect 04cdceaf7d88
"Mounts": [
            {
                "Type": "bind",
                "Source": "/home/yxx/centos-test",
                "Destination": "/home",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

# 观察对应目录是否出现1.java文件
yxx@yxx-virtual-machine:~/centos-test$ ls /home/yxx/centos-test/
1.java

# 即使容器停止了,修改主机目录,也会产生作用,因为再次启动容器之后发现,数据依旧是同步的

方式2:卷映射:分为具名挂载以及匿名挂载。不指定主机目录,挂载在/var/lib/docker/volumes/ 下面

docker run -it -v 卷名:容器内目录 镜像名/镜像id # 具名挂载,指定卷名
docker run -it -v 容器内目录 镜像名/镜像id # 匿名挂载,卷名是随机加密的,反正看不懂

# 找到对应主机目录方式1
docker volume ls # 查找所有卷
docker volume inspect 卷名 # 就可以得卷名的一些信息,包括挂载到的的具体地址等

# 发现 原来不指定主机内目录的话,卷都在/var/lib/docker/volumes/ 下面
yxx@yxx-virtual-machine:~/centos-test$ docker volume inspect b549995074151a22fa3c9c979adc5b284ea3312bacaa206b28226267dd2b2dfb
[
    {
        "CreatedAt": "2022-11-01T13:02:10+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/b549995074151a22fa3c9c979adc5b284ea3312bacaa206b28226267dd2b2dfb/_data",
        "Name": "b549995074151a22fa3c9c979adc5b284ea3312bacaa206b28226267dd2b2dfb",
        "Options": null,
        "Scope": "local"
    }
]
# 找到对应主机目录方式2
# 直接docker inspect 容器id 其中就有一个挂载信息

卷的权限(权限设定之后,容器对我们挂载出来的内容就有限制了)

docker run -it -v 卷名:容器内目录:权限 镜像名/镜像id
权限 包括 ro(只读,说明只能宿主机该,容器改不了) rw(读写都行,默认的)

Mysql同步数据练习:之后有空再做吧

容器与容器的数据交互

数据卷容器的思想:就是容器间共享数据卷,他们相当于是指针,指向主机中同一个目录,并且会有链接计数的概念,所以即使父亲容器停止了,删除了,子容器的数据卷也不会丢。但是一旦所有的容器都删除了,源数据就会消失,除非父容器将数据持久化到了本地。
例子:

# 创建容器docker01
yxx@yxx-virtual-machine:~/docker-test-volume$ docker run -it --name docker01 60b057c936b7
# 将docker01作为父容器创建docker03
yxx@yxx-virtual-machine:~/docker-test-volume$ docker run -it --name docker03 --volumes-from docker01 60b057c936b7
# 在docker03的数据卷volume01中写一个qw.java
[root@81ad74b5c0b1 /]# cd volume01
[root@81ad74b5c0b1 volume01]# touch qw.java
# 回到docker01中 发现确实同步过来了
[root@81ad74b5c0b1 volume01]# yxx@yxx-virtual-machine:~/docker-test-volume$ doc/bashxec -it 83dea9d1b22b /bin 
[root@83dea9d1b22b /]# cd volume01
[root@83dea9d1b22b volume01]# ls
qw.java

问题:这样的话,多个容器使用-volumes-from的操作和多个容器挂载同一个目录 有什么区别呢?

Dockerfile

镜像原理

分层镜像:拉取镜像是一层一层拉取的。因为镜像是分层的,所有的镜像都起源于一个基础镜像层,当进行修改或者增加新的内容的时候,就会在当前镜像层上创建新的镜像层。这样做的好处就是很多层可以共用,也就是拉取镜像的时候发现有些层我们已经有了,那么就只需要拉取那些没有的就好了。另一方面,我们将镜像run起来得到容器之后。相当于在原始的镜像层基础上加了一个容器层,接下来的操作就是在这个容器层的基础上做的,当我们要发布应用了,就将容器层+镜像层聚合成一个新的镜像。
在这里插入图片描述
提交容器成为一个新的镜像(和Git类似)

docker commit
docker commit -m="" -a="" 容器id 目标镜像名:[TAG]
# 可选项
-m # 提交的描述信息
-a # 作者

# 启动了nginx 并将我们操作过的容器提交为了一个新的镜像,之后可以使用我们自己的新镜像
yxx@yxx-virtual-machine:~/yxx$ docker start 41d6fc1059b8
41d6fc1059b8
yxx@yxx-virtual-machine:~/yxx$ docker commit -m="hello" -a="yxx" 41d6fc1059b8 nginx-yxx:1.0
sha256:af9a94cd14849a9b5314e6a4c26e974a3524a9749fb95ff6110e42ef768dc280
yxx@yxx-virtual-machine:~/yxx$ docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
nginx-yxx             1.0                 af9a94cd1484        5 seconds ago       141MB
nginx                 latest              605c77e624dd        10 months ago       141MB

制作镜像

Dockerfile是什么:就是用来构建docker镜像的构建文件,命令脚本。通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令就是一层。

初试dockerfile

# 创建一个dockerfile文件 文件名最好就叫这个
# 文件内容如下
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash


docker build -f dockerfile1 -t centos/yxx:2.0 .  # 创建镜像
# 运行镜像,得到容器
yxx@yxx-virtual-machine:~/docker-test-volume$ docker run -it centos/yxx:2.0 /bin/bash
[root@67e5af67b313 /]#
[root@67e5af67b313 /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volume02
dev  home  lib64  media       opt  root  sbin  sys  usr  volume01

# 发现volume01、volume02就是我们挂载的数据卷
# 问题来了,我们是怎么挂载的呢?显然什么都没有是匿名挂载。
# 那么对应的主机地址是?找到对应主机目录方式1、2

Dockerfile基础知识:

每个保留关键字(指令)都是大写字母
从上到下顺序执行
# 表示注释
每个指令都会创建提交一个新的镜像层

Dockerfile指令:

FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 添加的内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 指定暴露端口
CMD # 指定这个容器启动的时候需要运行的指令,只有最后一个会生效,可被替代(被run命令后面追加的命令替代)
ENTRYPOINT # 指定这个容器启动的时候需要运行的指令,可以追加命令(被run命令后面追加的命令 会被追加到ENTRYPOINT的参数列表中)
CMD ["",""] #不加[]就是执行单个指令,加就是执行多条命令,ENTRYPOINT命令同理 
ONBUILD # 当前镜像构建的时候不会执行,将当前镜像作为基础镜像构建下一级镜像的时候会被执行
COPY # 将文件拷贝到镜像中
ENV # 构建的时候设置环境变量

Dockerfile构建自己的centos:

# 编写dockerfile
FROM centos:7
MAINTAINER yxx<15168561119@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH

EXPOSE 80

CMD echo MYPATH
CMD echo "--end--"
CMD /bin/bash


# 构建镜像
docker build -f my-centos -t my-centos:1.0 .

Dockerfile构建自己的tomcat镜像:

以上的构建信息可以通过docker history查看

yxx@yxx-virtual-machine:~/dockerfile$ docker history my-centos:1.0
IMAGE               CREATED              CREATED BY                                      SIZE                COMMENT
b58bfe5d494d        About a minute ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B                  
6386be360689        About a minute ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
fb4525c5d664        About a minute ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
332e0ed4ec0e        About a minute ago   /bin/sh -c #(nop)  EXPOSE 80                    0B                  
fca9330d6753        13 minutes ago       /bin/sh -c #(nop) WORKDIR /usr/local            0B                  
b909544e4cfa        13 minutes ago       /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B                  
8a3801d2755c        13 minutes ago       /bin/sh -c #(nop)  MAINTAINER yxx<1516856111…   0B                  
eeb6ee3f44bd        13 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           13 months ago        /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
<missing>           13 months ago        /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB   

发布镜像到阿里云

发布到阿里云
阿里云->控制台->打开左边菜单出窗口,搜索容器镜像服务->点击个人实例->命名空间,创建命名空间->镜像仓库,选择刚才创建的命名空间,创建镜像仓库,(仓库信息中的仓库名称相当于是镜像名,代码源是本地仓库->使用阿里云命令了(登录、推送、下载)

流程图
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值