Docker
初识Docker
环境为Ubuntu

docker就是用于解决软件跨环境迁移的问题,docker简单来说就是装了软件及其运行环境的容器


ps:md,docker好几个源都不好用,我的/etc/docker/daemon.json配置如下
1 | /*配置如下*/ |
Docker架构与容器化


比如想在docker主机上运行MySQL,在docker客户机上拉取MySQL镜像(docker pull MySQL),然后docker主机就会在应用市场/仓库中下载MySQL镜像;
客户机上运行MySQL,执行run命令(docker run MySQL),就会创建容器,容器中放着一个或者多个应用

也可以制作自己的镜像,docker build xxx,会放在docker主机的image中,也可以将这个镜像上传到应用市场中,
docker push xxx
命令
命令-镜像操作

eg:下载一个nginx
先查看仓库中有没有nginx的镜像,sudo docker search nginx(search不走配置的镜像源所以会超时,在镜像名前加上 register.liberx.info/可以解决超时问题)
然后拉到docker主机,sudo docker pull nginx,pull默认是下载最新版本,下载指定版本nginx:版本号
查看自己的镜像列表:sudo docker images/sudo docker image ls
命令-容器操作

查看运行中/所有容器: sudo docker ps [-a]加上-a就会显示所有容器

UP表示上线,EXITED表示结束运行
sudo docker start/stop/stats后面加的是容器名字或者容器的id(id不一定全部输完只要能区分就行,但是名字不能模糊匹配)

删除容器:sudo docker rm [-f] 容器名/容器id,不加-f那么需要停止容器再删除,-f表示强制删除
可以用$传入id
sudo docker rm -f $(sudo docker ps -aq) -aq是显示所有容器的ID
命令-run,exec
运行的docker容器名字一坨,一run就阻塞终端,怎么办?
sudo docker run -d --name 想要指定的容器名 镜像名

-d表示后台运行,–name(是两个杠)给容器指定一个名字
既然占用80端口了,计网里学的80是web服务端口,那么想必可以可以用浏览器访问吧

虽然nginx运行了,还占用的80端口(web服务默认端口),但是在浏览器直接访问docker host的ip行不通

为什么会这样呢?
原因是占用的80端口只是容器的80端口而不是主机的80端口(前面说的容器就像一个更简化的虚拟机,内部的端口自然与外部主机的端口不一样),所以我们需要进行端口映射
-p 外部端口:内部端口(非常重要!!!!!)

将主机的80端口映射到容器的80端口
这下访问到nginx的主页了

怎么修改默认的这个页面呢?dockerhub中会描述镜像的默认初始页面(usr/share/nginx/html)(我上不去啊)
sudo docker exec -it 容器名 /bin/bash -it表示交互模式,/bin/bash表示以终端方式进入这个容器

exit退出
命令-镜像操作

sudo docker commit [选项] 选定容器 镜像
1 | -a, --author:设置镜像作者信息。 |
比如将前面的运行nginx的容器提交为新镜像
sudo docker commit -m "commit-test" -a "wwwtty" myNginx committest

镜像保存为一个tar文件
sudo docker save [-o 文件名.tar] 镜像名
sudo docker load -i tar包名字
load下来后就是一个镜像,直接run就可以启动容器


sudo docker login
需要有dockerhub账号
sudo docker tag 原镜像名 目标镜像名
sudo docker push 目标镜像名
存储
容器内部对文件修改困难(没有vi/vim),而且如果容器炸了或者容器重新启动就丢失修改
目录挂载
外部的目录像u盘一样 -v 外部目录:内部目录
比如将~下的html目录作为外部目录,nginx默认页面所在目录作为内部目录
sudo docker run -d --name test -p 80:80 -v ~/html:/usr/share/nginx/html nginx
这样访问服务器ip出来的就是自己预设的页面
卷映射
如果想通过修改外部文件就能实现对内部配置文件的修改,需要使用卷映射
为什么不能使用目录挂载呢,因为目录挂载如果目录不存在,会先在外部创建一个空文件夹,那么挂载空文件夹,相当于启动时配置项全是空的,就启动不了容器
-v 卷名:容器中配置文件路径
卷的位置 /var/docker/volumes/卷名
显示所有的卷:sudo docker volume ls
创建卷:sudo docker volume create 卷名
显示卷的详细信息:sudo docker volume inspect 卷名
网络
容器间访问
怎么实现一个容器访问另一个容器?
1.可以通过run的-v端口映射
我有以下两个run起来的容器

假设从test1访问test
sudo docker exec -it test1 bash
sudo curl 175.27.249.106:80
终端就会出现html

但是这样做很奇怪,相当于从test1的88端口->docker host的80端口->test的80端口,绕了一大圈
有一个叫做docker0的默认网络

查看容器细节:sudo docker container inspect 容器名/sudo docker inspect 容器名

接下来就可以通过显示出的IP地址进行访问(docker为每个容器分配唯一IP,通过ip+容器端口可以互相访问)
从test0访问test1

1 | ubuntu@VM-0-9-ubuntu:~$ sudo docker exec -it test0 bash |

这样做也有缺点,ip是会变动的
创建自定义网络

创建mynet:sudo docker network create mynet

将容器加入自己的网络下(–network 网络名) sudo docker run -d --name test0 -p 80:80 --network mynet nginx
sudo docker inspect test0:

这样一来,容器间访问只需要进入容器->curl http://容器名:容器端口
Docker compose


上线:第一次创建并启动
下线:移除创建的容器以及相关资源
不用compose.yaml启动wordpress和mysql
1 | #启动mysql |
compose.yaml格式:
1 | name: 项目名 |
启动(上线)命令:sudo docker compose -f compose.yaml up -d
-d:后台运行
-f:指定yaml文件
下线命令:sudo docker compose -f compose.yaml down
如果更改了compose.yaml文件的配置,重新上线,没有被更改的应用会保持running状态;
下线并不会移除对应的卷
Dockerfile
dockerfile制作镜像


比如将app.jar打包成镜像
1 | FROM openjdk:17 |
制作镜像命令:docker build -f dockerfile -t 镜像名:版本 ./要指明当前的目录./
镜像分层存储


使用docker history 镜像名查看容器构建历史(过程自下而上)
也可以使用 docker image inspect 镜像名查看更详细的信息
官方的nginx镜像(docker history):

(docker image inspect)展现的层级:

进行目录挂载后的容器再commit的镜像:

发现多了1.09kb
(docker image inspect)展现的层级:

比官方的多了一层,多的一层就是挂载的目录
分层视角下的容器与镜像
容器就是在镜像层(只读)加上一层读写层,对容器的修改都是在可读可写层进行,所以删除容器修改都会丢失(因为读写层没了)
这样的好处是容器隔离:

可以用 docker ps -s/--size 查看读写层和只读层的关系

SIZE列 前面是读写层大小括号内是镜像大小




