—— 目录 ——
1. 安装 Docker
① 查看服务器环境
cat /etc/os-release:查看系统内核版本(确认在 3.10 以上)
uname -r:查看服务器版本
② 卸载旧的 docker(确保没有下载)
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
显示这个,说明系统中并没有安装旧的 docker,可以进行安装
③ 修改 docker 镜像
# 安装需要的工具包
yum install -y yum-utils
# 设置镜像仓库(默认是国外的)
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
④ 更新 yum 索引,并安装启动与使用最新的 docker
yum makecache fast
——— 404 错误处理 ———
▲ 如果使用的服务器是(Aliyun Linux 2.1xxx),是这里就有一个巨坑(不是的话请跳过)
在执行这段命令时,会出现一下报错
https://mirrors.aliyun.com/docker-ce/linux/centos/2.1903/x86_64/stable/repodata/repomd.xml: [Errno 14] HTTPS Error 404 - Not Found
起初认为时镜像出问题了,一番查找后,发现时版本出现了问题
这种阿里云的服务器,$releasever
值为 2.1xxx,而 centOS7 的该值为 7
这就导致了版本匹配不上,安装失败
这时,我们只需要将 /etc/yum.repos.d/docker-ce.repo
这个文件夹中的 $releasever
全部替换为 7 ,就可以正常执行了!
附上全局修改命令::%s/$releasever/7
(将所有的 $releasever 替换为 7)
——— 404 处理结束 ———
接下来是安装指令(会由选项,一直 y 就可以了),接着是启动指令与基本使用
安装:yum install docker-ce docker-ce-cli containerd.io
启动:systemctl start docker
验证是否启动成功:docker version
有显示内容,就表示已经启动成功了
基本使用:docker run hello-world
首次使用会出现 Unable to find image 'hello-world:latest' locally 找不到镜像,等它下载完就好了
查看已经安装了的镜像:docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 6 months ago 13.3kB
就可以看到刚刚安装的 hello-world 镜像了
⑤ 卸载 docker
需要卸载时,需要卸载依赖以及资源
# 1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 2. 删除资源(其中 /var/lib/docker 是 docker 的默认工作路径)
rm -rf /var/lib/docker
2. Docker 基本使用
① 镜像命令
1) 查看所有镜像
docker images
2) 搜索镜像
docker search xxx
3) 下载镜像(加上 tag 可以指定版本,不写默认是 lastest 最新
docker pull <镜像名>[:tag]
4) 删除镜像(后面可跟多个名字或者id,同时删除多个镜像)有以下两个
镜像 id 可以取前 n 个(一般 3 个就可以了),只要能唯一找到一个镜像即可
docker rmi [-f] <名字/id>
docker image rm <名字/id>
5) 删除全部镜像($ 中的命令为列出所有 docker 的 id,然后批量删除)
docker rmi -f $(docker image -aq)
② 容器命令
可以先下载一个 centos 来测试,然后启动容器
docker pull centos
1) 创建并启动容器(注意和下边 docker start 的区别哦)
docker run [选项] <镜像名>
--name="xxx" 给容器起名字
-d 后台方式运行
-i 使用交互式方式运行(让容器的标准输入保持打开)
-t 为容器分贝一个伪终端,并绑定到标准输入上(一般联合使用为 -it)
-p 指定容器的端口
可以是(主机端口:容器端口,如 8080:8081,将主机 8080 端口映射到容器的 8081 端口)
也可以直接写容器端口
-P 随机指定端口
————————
测试一波(后边的 /bin/bash 是为 -it 交互式指定控制台)
docker run -it --name='myCentos' centos /bin/bash
接下来就是套娃了~
可以在这个 centos 容器中做原本服务器可以做的事
比如前面的
cat /etc/os-release:查看系统内核版本
uname -r:查看服务器版本
内部的这个 centos 和外部我们自己的服务器没有关系,隔离开来了,可以随便玩
————————
2) 退出容器
exit 退出容器,如果容器没有被使用,会自动停止
Ctrl + P + Q 容器不停止并退出,仍和情况下不会停止容器
3) 查看所有运行的容器
docker ps [选项]
-a 加上曾经运行过的容器
-n=? 列出最近的 n 各容器
4) 删除容器(在运行中的容器,需要加上 -f 才能成功删除)
docker rm [-f] <容器id>
5) 进入正在运行中的容器
docker exec <id>
可使用 docker exec -it <id> /bin/bash 交互式进入,会新开一个终端
由于新开了一个终端,故使用 exit 后,原容器并不会停止哦(比较推荐使用)
docker attach <id>(进入容器当前终端)
6) 容器四件套
docker start <id> 启动容器(要求容器已经被创建)
docker restart <id> 重启容器
docker stop <id> 停止容器
docker kill <id> 强制停止容器
7) 从容器中拷贝东西到主机上
docker cp <容器id>:<容器内路径> <目前主机路径>
2021-10-1
1) 从主机复制文件(夹)到容器
docker cp <主机路径> <容器id>:<容器路径>
2) 从容器复制文件(夹)到主机
docker cp <容器id>:<容器路径> <主机路径>
③ 辅助命令
1) 显示 docker 版本信息
docker version
2) 显示 docker 详细信息,包括了镜像和容器的数量等等
docker info
3) 查看帮助文档,中间 加上指定命令,可以看到相应命令的帮助c
docker [命令] --help
4) 查看日志
docker logs [选项] <容器id>
-f 动态显示日志(和 tail -f 一样功能)
-t 显示时间戳
5) 查看进程信息
docker top <容器id>
6) 查看容器内部信息
docker inspect <容器id>
7) 提交自己的镜像
docker commit -a="作者" -m="描述信息" <容器id> <镜像名>
2021-10-1
1) 查看 docker 占用的空间
包括井下镜像、容器、数据卷和缓存
加上 -v 可以看到更详细的信息
docker system df [-v]
3. 容器数据卷
之前将应用和环境打成一个包后,数据也一并存放在容器中了
这样将直接导致数据随着容器的删除而一起销毁
所以如果我们希望数据可以分离出来,保存在本地,就需要用到数据卷了
数据卷特性:
- 可供一个或多个容器使用,实现容器之间数据的共享和重用
- 对数据卷的修改会立即生效
- 数据卷将一直存在,即使容器被删除
① 基本操作
1) 查看所有数据卷
docker volume ls
2) 查看指定数据卷的信息
docker volume inspect <数据卷名>
3) 删除数据卷
docker volume rm <数据卷名>
如果想在删除容器时顺便删除数据卷,可使用
docker rm -v
也可以清理无主的数据卷(没有容器使用,但可能该数据还有用,考虑后使用)
docker volume prune
4) 在启动时挂载一个数据卷,两种方式
docker run -v <主机路径>:<容器路径>
docker runb --mount source=<数据卷名>
区别是,-v 会自动创建不存在的文件夹,而 --mount 在文件夹不存在时会抛出错误
例如以下,将 tomcat 的日志文件夹。挂在到主机的指定目录中
docker run -it -v /home/iceclean/docker/tomcat-log:/logs/ tomcat /bin/bash
挂在完毕后,主机和容器任意一个修改,对方该目录下也会相应生成文件,这样,当容器被删除时,数据也会被安全的保存在服务器主机中
② 向已经启动的容器挂载数据卷
具名挂载与匿名挂载
前边的操作,是直接映射了地址,在实际开发中也可以让数据卷存放在 docker 统一的目录下
在 -v
后面,不写主机目录,默认就是匿名挂载,名字是一串编码
将主机名字写成数据卷名字(区别在于最前面不带 / 号),就可以在统一目录下生成一改名字为文件夹的数据卷
4. DockerFile
dockerfile
是用来构建 docker 镜像的文件
在该文件中,每一个命令就是一层,基本命令如下
① FROM 指定基础镜像 <必须有>
该镜像以一个镜像作为基础,所以首先得有一个基础的镜像(FROM 引入)再进行我们自己个性化的处理
如果不想以任何镜像作为基础,可以使用 FROM scratch
,其中 scratch 表示一个虚拟的进项,并不实际存在,是一个空白的镜像
② RUN 执行命令
RUN
指令可以用来执行命令行命令,再构建镜像中是经常用到的,其格式有两种
- shell 格式:RUN 命令,就像直接再命令行输入命令一样
- exec 格式:RUN [“可执行文件”, “参数1”, “参数2” …],这可以启动一个可执行文件
由于每个命令是一层,在执行该命令时,都相当于启动一个容器,然后执行命令
所以如果将 RUN
命令分开写,将会导致层数激增,每次都启动一个新的容器执行一个命令
这将增加部署时间,所以在编写 RUN
命令时,一般做如下改进
RUN touch /usr/local/test.txt
RUN echo 'test' > /usr/local/test.txt
RUN cp /usr/local/test.txt /var/
这样写就相当于三层,但实际上只做了一层的工作量,可以简化为一层,如下
RUN touch /usr/local/test.txt \
echo 'test' > /usr/local/test.txt \
cp /usr/local/test.txt /var/
这里还有一个值得注意的点
由于每一个 RUN 都时新开一个容器,所以命令之间是不会互相作用的,如
RUN cd /xxx
RUN cat xxx.txt
这两行命令分开写,将直接导致 xxx.cat 并非在 /xxx 目录下寻找,而是在工作目录中寻找
为了避免出这种错误,就更应该写成一层了,如下
RUN cd /xxx \ cat xxx.txt
通过这两步就可以构建简单的镜像啦
执行 docker build -f <文件所在路径> .
注意:命令的最后有一个 .
,该点指定了上下文路径,docker build
命令会将该目录下的文件打包交给 Docker 引擎以协助构建镜像
除此之外,dockerfile
还有很多肺功能强大的命令
③ ENV 设置环境变量
④ VOLUME 挂载匿名卷
该命令可以实现指定容器数据存放的位置,避免当用户没有指定数据卷时,容器中的数据直接写在了容器的存储层中破坏掉容器的无状态化
将容器里 /data 中的数据挂载到服务器主机中
任何向 /data 中写入的信息不会被记录到容器的存储层中,而是保存在服务器主机中
当然,用户在运行容器时也可以手动指定覆盖这个设定
VOLUME /data
⑥ EXPOSE 声明暴露端口
格式为 EXPOSE <端口1> [端口2 端口3 ...]
该指令可以声明容器运行时提供服务的端口
注意:该指令只是一个声明,并不会真正开启这个端口的服务,当用户使用 -P
进行随机端口映射时,会自动映射到这个端口。同时也是方便用户的配置,告知用户建议配置那个端口
⑦ WORKDIR 指定工作目录
格式为:WORKDIR <工作目录路径>
指定后,各层的当前目录会被改成指定的目录(即第一次进入时,就在该目录里边)
目录如果不存在,会自动创建一个
5. Docker 网络
网络模式
- bridge:桥接模式(默认)
- none:不配置网络
- host:和主机共享网络
1) 查看所有的 docker 网络
docker network ls
2) 指定网络(不写 --net xxx,默认为桥接模式)
docker run [--net bridge] <容器名>
6. 自定义脚本安装 Docker
…待
7. 旅行者日记
① 该死,容器里边命令不全,咋整
按照查到的方案,执行以下命令:
更新资源
apt-get update
安装 ping 命令
apt-get install iputils-ping
安装 ps 指令
apt-get install procps
接着出现了下一个问题,容器连不上网?(请往下看)
② docker 端口映射后,外网访问不到
描述:
阿里云安全组和服务器防火墙都打开了对应的映射端口,服务器内可以通过 localhost:xxxx 可以正常访问到容器,但外网却怎么页访问不到
一番查找后,发现了一个大问题:容器内部连接不上网络
在容器中使用 ping
命令无反应(服务器主机可以)
然后按照网上说法,是 docker 的默认网段和阿里云服务器的网段冲突了
所以对 docker 的网桥进行了如下修改:
service docker stop
ip link set dev docker0 down
brctl delbr docker0 (这里需要进行下载 yum install bridge-utils)
然后修改 /etc/docker/daemon.json 文件(如果没有的话新建),改为以下
{
”bip“:"192.168.100.1、24"
}
————————
中间出现了小插曲
要启动 docker 时,报以下错误
# Job for docker.service failed because the control process exited with error
# Failed to start Docker Application Container Engine
使用所有的 docker 命令,都报
# Cannot connect to the Docker daemon at unix:///var/run/docker.sock
后来发现,是该文件写的不对,和其他配置冲突了
由于情况很多,这里视情况修改这个文件即可,不需要改动其他
————————
修改完毕后,执行
systemctl daemon-reload
systemctl restart docker
但是发现还是 ping 不通… 枯了
再一番尝试,发现当容器网络设置为 host 时,容器内部可以联网,如
docker run -it --network=host tomcat /bin/bash
———— 插曲 ————
当使用 host 网络可以联网后,这时端口已经和主机是共用的了
所以诸如 tomcat,nginx 都不能使用默认端口了
于是我将 nginx 端口修改(阿里云安全组与服务器防火墙已打开)
但发现外网依旧无法访问容器???
最后发现,在手机上可以,而不基本不行
唯一的区别就是,笔记本使用了 VPN ,而收集没有
是否因为 VPN 导致了访问不了容器?又该怎么解决?
后来的后来,发现不是 VPN 的问题,换成 tomcat 没问题可以正常访问
但是奇了怪了,在服务器可以通过域名+端口访问 nginx,为什么到浏览器就不行了呢
命名 tomcat 也是一样的操作,放到浏览器却可以?
———— 插曲 ————
到这里已经基本上可以确认,是网桥模式的问题,使得容器无法通过外网访问
… 等我
2021-9-30 联网问题解决了
就在今天,我发现服务器的端口号既然跑到了 10w+,服务器直接崩溃了
很纳闷,端口号的上限,不应该是 65535 嘛?为什么会这样(附上之前很疑惑的一张截图)
可以看到此时的 PID 已经到了 7w+ 不知道是什么原因
但就在服务器重启之后,所有的容器内,都能 ping 通了
以前只有指定 --network=host
才能使容器 ping 同外网,现在无论什么操作都 ok 了
仔细检查了配置文件,发现和上边写的一样,难道是必须服务器重启后这它生效吗?
明显不是的,之前重启 docker 时,使用 ifconfig 已经看到它生效了
嘛,虽说问题总算解决了,但又留下了两个坑:
为什么端口号超过了 65535,直到 10w+ 时服务器才崩溃?
为什么 docker 容器突然就能访问外网了?
…继续等我
我一定会回来的 -_-(IceClean)