什么是docker
Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。
有些人说docker是容器,又有人说docker不是容器,在我看来,docker更像是一个装载容器的容器;,大船就是一个容器,然后每一个集装箱又是一个小容器;我们看看docker的图标就知道;
而最主要的,就是镜像分层的概念;最下面是是操作系统,倒数第二层基础镜像,中间是我们在基础镜像上装的服务,最上面是容器层;乍一看,好像容器嵌套;
介绍完了docker,我们在看看docker都有哪些命令吧!
启动和停止docker
# 启动
systemctl start docker
# 守护进程重启
sudo systemctl daemon-reload
# 重启docker服务
systemctl restart docker
# 重启docker服务
sudo service docker restart
# 关闭docker
service docker stop
# 关闭docker
systemctl stop docker
帮助命令
docker version # 查看版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help # 帮助命令
==-aq表示-all[所有的] 和-quiet[只显示id]的集合==
镜像命令
[root@VM_0_5_centos ~]# docker images # 查看所有镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 4 weeks ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像id
CREATED 镜像的创建时间
SIZE 镜像大小
docker images -q # 只显示ID
搜索镜像 docker search
docker search mysql # 搜mysql镜像
docker search mysql --filter=stars=3000 搜mysql镜像收藏数3000以上的
下载镜像 docker pull
下载镜像也可以通过网站去查询: https://hub.docker.com/_/redis
[root@VM_0_5_centos ~]# docker pull redis # 下载redis镜像,默认下载最新版本的
Using default tag: latest
latest: Pulling from library/redis
7d63c13d9b9b: Pull complete # 分层下载,如果有之前有下载过相同的文件,就可以共用,把一个文件分成好几个文件,类似rar的分卷压缩
a2c3b174c5ad: Pull complete
283a10257b0f: Pull complete
7a08c63a873a: Pull complete
0531663a7f55: Pull complete
9bf50efb265c: Pull complete
Digest: sha256:a89cb097693dd354de598d279c304a1c73ee550fbfff6d9ee515568e0c749cfe # 签名
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest # 真实地址 docker pull redis 和 docker pull docker.io/library/redis:latest 是一样的
docker pull redis:5.0 # 下载指定版本的redis
删除镜像 docker rmi
docker rmi -f $(docker images -aq) 删除所有的镜像
docker rmi -f 02fee89f17ad # 删除指定id的镜像
查看镜像构建历史
docker history 镜像id
容器命令
说明
有镜像才能创建容器;所以先下载一个centos系统
docker pull centos
新建容器并启动
# 根据镜像创建容器,并且启动容器进入容器
docker run --name contos_3 -p 9090:80 -it centos /bin/bash
# 参数说明
--name cname 容器的名字,如果未配置,docker会自动帮你起一个名字
-d 后台方式运行
-it 使用交互方式运行
-p (小写p)指定容器的端口
-p ip:主机端口:容器端口
-p 主机端口:容器端口
-p 容器端口
容器端口
-P (大写P)随机映射端口
/bin/bash 进入容器后新开启一个终端
开放多个端口
docker run -p 8080:8080 -p 8081:8081 nginx
开放范围端口
docker run -p 8080-8090:8080-8090 nginx
用完即删 —rm
我们在测试的时候,测完了没问题了,这时候就需要将容器给删除了,每次自己手动去删除会有些麻烦,所以docker给出了一个参数--rm
,可在停止容器的时候顺便将容器删掉,用法如下
# tomcat的官方用法,这种用法一般用在tomcat身上
docker run -d --rm centos
# 当运行以下命令停止docker时就会删除容器
docker rm -f 容器id/容器名称
常见的坑
通过以下命令后台运行时,发现并没有将centos运气起来,这是因为要使容器后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止;像nginx一样,容器启动之后,发现自己没有提供服务,就会立即停止;
# 此命令会停止容器
dockers run -d centos
# 以下命令因为有前台进程,所以容器不会停止
dockers run -d -it centos
如何打通宿主机和容器
在新建容器时有一个非常重要的参数-p 8080:80
,这个参数就是打通宿主机和容器使用的,也就是说,当我们在外部访问localhost:8080
时,实际访问的是容器的80
端口,新建容器的完整命令如下
docker run -p 9090:80 centos
打通多个端口
像tomcat这样的服务器有三个开放的端口,分别是8080、8005、8009,那么这时候如果我们想要将这些端口都开放出去应该怎么做呢?其实很简单,只需要配置多个-p
就可以了
docker run -d -p 8080:8080 -p 8005:8005 tomcat
退出容器
eixt # 注意:这边是直接让容器停止运行了
ctrl + P + Q 快捷键可以回到主系统,但是不退出容器
启动或停止容器
docker start 容器id # 启动容器,只能启动已经创建好的容器
docker restart 容器id/容器名称 # 重启容器
docker stop 容器id/容器名称 # 停止容器
docker kill 容id/容器名称 # 强制停止容器
查看所有的容器
docker ps -a # 查看运行过的容器;-a表示-all(所有的)
查看正在运行的容器
docker ps # 查看所有正在运行的容器
进入正在运行的容器
# 方式一:进入容器后开启一个新的终端
docker exec -it 容器id/容器名称 /bin/bash
# 方式二: 进入容器后使用正在执行的终端
docker attach 容器id/容器名称
删除容器
```shell
docker rm 容器id/容器名称 # 删除指定容器 ,不能删除正在运行的容器
docker rm -f 容器id/容器名称 # 删除指定容器 ,也能删除正在运行的容器
docker rm $(docker ps -aq) # 删除所有容器,不能删除正在运行的容器
docker rm -f $(docker ps -aq) # 删除所有容器,包含运行的容器
> 查看日志
```shell
docker logs -f -t --tail 10 容器id
# 说明
-f 跟踪日志输出,会一直显示最新的日志内容;和tail -f是一样的;
-t 打印时间戳
--tail 10 只显示10行
查看容器中的进程
docker top 容器id/容器名称
查看容器的元数据
docker inspect 容器id/容器名称
将容器内的文件拷贝到宿主机
docker cp 容器id/容器名称:容器内路径 宿主机路径
查看容器状态命令
docker stats
展示内容如下
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c75c62eff5f6 tomcat_1 0.16% 126.3MiB / 1.796GiB 6.87% 28.4kB / 233kB 20MB / 0B 29
# 说明
CONTAINER ID 容器id
NAME 容器名称
CPU % CPU使用率
MEM USAGE 使用了多少内存
LIMIT 总内存
MEM % 内存使用率 ,以百分比的形式显示内存使用情况
NET I/O 网络 I/O 数据。
BLOCK I/O 磁盘 I/O 数据。
PIDS 进程id
限制容器内存大小
为什么要限制容器内存大小?
对于 linux 主机来说,一旦内核检测到系统没有足够的内存可以分配,就会杀死一些进程来释放内存空间,糟糕的是任何进程都可能成为内核猎杀的对象,所以为了不让其他重要进程被误杀,就有必要对容器的内存使用做一些限制;
SWAP 虚拟内存和物理内存的区别
在此之前我们得先了解一下虚拟内存,在详细介绍swap之前,我们需要知道的是计算机对内存分为物理内存与虚拟内存(注意虚拟内存和虚拟地址空间的区别)。物理内存就是计算机的实际内存大小,由RAM芯片组成的。虚拟内存则是虚拟出来的、使用磁盘代替内存。虚拟内存的出现,让机器内存不够的情况得到部分解决。当程序运行起来由操作系统做具体虚拟内存到物理内存的替换和加载(相应的页与段的虚拟内存管理)。这里的虚拟内存即所谓的swap。
限制容器内存
# -m 300M 限制容器内存大小为300M
docker run -d --name nginx_2 -p 8000:80 -m 300M --memory-swap -1 nginx
以上的命令主要关注2个参数,分布是 -m
和 --memory-swap
,其中-m
是 --memory
的缩写 ,执行docker run
命令时能使用的和内存限制相关的所有选项如下
| memory | memory-swap |效果|
|—|—|—|
| M | 正数 S | 容器最大可用内存为S,其中 物理内存为 M,虚拟内存 为(S - M),若 S=M 则表示没有可用的虚拟内存资源|
| M|0 |相当于未设置 虚拟内存 |
| M| -1| 容器最大可用内存为 M+主机可用的物理内存|
|M | 未设置 | 容器最大可用内存为 2M,其中 ram 为 M,swap 为 M|
使用不同的配置可达到不同的效果,以下是不同配置时达到的效果
1. 不设置
如果不设置-m,—memory和—memory-swap,容器默认可以用完宿舍机的所有内存和 swap 分区。不过注意,如果容器占用宿主机的所有内存和 swap 分区超过一段时间后,会被宿主机系统杀死(如果没有设置--00m-kill-disable=true
的话)。
2. 设置-m,—memory,不设置—memory-swap
给-m或—memory设置一个不小于 4M 的值,假设为 a,不设置—memory-swap,或将—memory-swap设置为 0。这种情况下,容器能使用的内存大小为 a,能使用的交换分区大小也为 a。因为 Docker 默认容器交换分区的大小和内存相同。
如果在容器中运行一个一直不停申请内存的程序,你会观察到该程序最终能占用的内存大小为 2a。比如$ docker run -m 1G ubuntu:16.04
,该容器能使用的内存大小为 1G,能使用的 swap 分区大小也为 1G。容器内的进程能申请到的总内存大小为 2G。
3. 设置-m,—memory=a,—memory-swap=b,且b > a
给-m设置一个参数 a,给—memory-swap设置一个参数 b。a 时容器能使用的内存大小,b是容器能使用的 内存大小 + swap 分区大小。所以 b 必须大于 a。b -a 即为容器能使用的 swap 分区大小。
比如$ docker run -m 1G --memory-swap 3G ubuntu:16.04
,该容器能使用的内存大小为 1G,能使用的 swap 分区大小为 2G。容器内的进程能申请到的总内存大小为 3G。
4. 设置-m,—memory=a,—memory-swap=-1
给-m参数设置一个正常值,而给—memory-swap设置成 -1。这种情况表示限制容器能使用的内存大小为 a,而不限制容器能使用的 swap 分区大小。
这时候,容器内进程能申请到的内存大小为 a + 宿主机的 swap 大小。
提交镜像 commit 当前容器生成新镜像
docker commit -a="作者" -m="说明" -p 容器id/容器名称 镜像新名称:镜像版本
# 举例,制作当前的tomcat容器生成镜像
docker commit -a="yexindong" -m="首次制作的镜像" tomcat_1 mytomcat:1.0
# 参数说明
-a :提交的镜像作者;
-c :使用Dockerfile指令来创建镜像;
-m :提交时的说明文字;
-p :在commit时,将容器暂停。
挂载 -v
运行以下命令后,就会将本机目录挂载到容器目录上,会在容器和宿主机上自动创建相应的目录,在目录下创建或者修改文件都会自动同步过去;
docker run -d -v 主机目录:容器目录 tomcat
如果需要挂载多个目录,只需要配置多个-v
就可以
docker run -d -v 主机目录:容器目录 -v 主机目录:容器目录 tomcat
配置容器环境变量 -e
e是environment的缩写,
以下是设置mysql的初始密码为:123456
docker run -d -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
第一种方式:以下方式可以查看容器中已经配置环境变量
docker exec "容器名称或者容器id" env
第二种方式:通过inspect查看,找到Env项里面的就是环境变量了;-A 10表示打印后面10行
docker inspect 容器id/容器名称 | grep Env -A 10
结果如下
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
镜像保存、加载
如果需要将自己构建的镜像发送给别人,又不想通过仓库来共享,就可以用镜像保存的功能,
镜像保存
首先我们将镜像以文件的方式保存到本地磁盘
docker save 镜像id/镜像名称 -o /本地目录/文件名称
# 比如这样
docker save ad8a585d32e3 -o /root/dockerFile/xx.tar
# 运行后,就可以看到,文件已经保存成功了
[root@VM_0_5_centos dockerFile]# ll
total 356440
-rw------- 1 root root 364991488 Oct 28 18:45 xx.tar
加载已保存的镜像
使用load命令加载,看到如下内容,表示镜像已经加载成功了
[root@VM_0_5_centos dockerFile]# docker load -i /root/dockerFile/xx.tar
2fefb3e7f055: Loading layer [==================================================>] 47.6MB/47.6MB
8b589f61fd94: Loading layer [==================================================>] 58.82MB/58.82MB
753a6b1d88c8: Loading layer [==================================================>] 19.99MB/19.99MB
Loaded image ID: sha256:ad8a585d32e34b301aab4b278704a908f6eca53884fd531a79859dd6054a22ae
接下来我们看看镜像已经加载好了,但是还没有名字
[root@VM_0_5_centos dockerFile]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> ad8a585d32e3 2 hours ago 356MB
接下来使用tag
命令给这个镜像起个名字和版本号吧
[root@VM_0_5_centos dockerFile]# docker tag ad8a585d32e3 xindong_tomcat_2:1.0
# 在看看镜像,已经有名字了
[root@VM_0_5_centos dockerFile]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xindong_tomcat_2 1.0 ad8a585d32e3 2 hours ago 356MB
在宿主机上执行容器内的命令
docker exec -it 容器id/容器名称 需要执行的命令
# 比如我想要查看容器内的网卡
docker exec -it tomcat_01 ip addr
网络命令 network
查看本机docker所有网络
docker network ls
创建网络
—driver 是网络模式,—subnet是子网掩码,后面的/16表示可以生成6万多个ip, —gateway是网关地址
docker network create 网络名称 --driver bridge --subnet 192.168.0.1/16 --gateway 192.168.0.2 mynet
将容器加入到当前网络
docker network connect 网络名称 容器名称
断开容器的网络 (容器必须是运行状态才能断开连接)
docker network disconnect 网络名称 容器名称
查看网络的详细信息
docker network inspect 网络id/网络名称
删除网络
docker network rm 网络id/网络名称
删除所有未使用的网络
docker network prune --f
完
到此为止,docker的常用命令就这么多,对于日常开发的童鞋来说也够用了;最后一张图总结下