什么是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 进入容器后新开启一个终端

用完即删 --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/容器名称

删除容器

docker rm 容器id/容器名称  # 删除指定容器 ,不能删除正在运行的容器

docker rm -f 容器id/容器名称  # 删除指定容器 ,也能删除正在运行的容器

docker rm  $(docker ps -aq)  # 删除所有容器,不能删除正在运行的容器

docker rm -f $(docker ps -aq)  # 删除所有容器,包含运行的容器

查看日志

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命令时能使用的和内存限制相关的所有选项如下

memorymemory-swap效果
M正数 S容器最大可用内存为S,其中 物理内存为 M,虚拟内存 为(S - M),若 S=M 则表示没有可用的虚拟内存资源
M0相当于未设置 虚拟内存
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的常用命令就这么多,对于日常开发的童鞋来说也够用了;最后一张图总结下
在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐