docker实践总结——docker常用命令

介绍

docker之前就有过了解,最近工作中有用到,便准备系统的学习一下,顺便通过博客的形式做笔记。

docker和虚拟机(如VMware)的区别:docker比虚拟机要轻量级,虚拟机是模拟硬件,然后在虚拟的硬件上安装操作系统,操作系统本身就是重量级软件,而docker则是基于容器的虚拟化技术,你可以把容器理解为沙箱环境,当然容器化的技术是依赖于操作系统的,在Linux中是基于cgroups来实现的,Windows家庭版安装docker貌似还是依赖虚拟机(Windows专业版则基于Hyper-V实现)。容器中只会有需要运行的应用以及它依赖的必要库(比如依赖一些操作系统的必要库文件,而不向虚拟机一样需要整个操作系统)。docker容器中的软件是直接与系统通信,而虚拟机中的软件与系统通信则多了一层“从操作系统”(虚拟机中的操作系统)。

举个例子,假设我电脑上已经安装了MySQL,但是我需要安装另外一个版本的MySQL做测试用,如果我使用虚拟机,则需要在电脑中安装并启动一个虚拟机,在虚拟机中安装操作系统,然后在虚拟机操作系统中安装MySQL,整个虚拟机跑起来占用资源是相当大的(操作系统+MySQL)。
如果我使用docker,则只需要一个MySQL镜像,将镜像加载到容器中,然后启动容器,这样就运行了一个完全独立于本机的MySQL服务,效果与虚拟机的完全一样,而且这个MySQL服务占用的资源很小,只有MySQL软件本身和一些必要的库文件(必要的库+MySQL),而不是整个操作系统+MySQL软件,非常轻量级的。


几个概念

docker的三个重要概念:

  1. 镜像
    在docker中,镜像属于只读层,可以理解为一个软件包,有点类似操作系统镜像的IOS文件,不过比操作系统较轻量级很多。
  2. 容器
    简单的说,容器可以理解为一个镜像在docker中的实例,容器启动之后便是 docker daemon 的一个子进程,同一个镜像可以多次运行,可以形成多个容器,每个容器都会有一个容器ID(containerID),当然你也可以指定一个容器名称(containerName),容器名称要唯一。
    用面向对象语言来打个比方,如果用Java语言中的类来比作镜像(如Thread类),则容器是这个类的一个对象实例(即 new Thread()),容器本身可以运行和停止,有点像 thread.start() 和tread.stop(),这个比方不一定恰当,能够增强理解就行。
    注意: docker本身不是容器,它是创建容器的工具,是一个容器引擎。
  3. 仓库
    仓库是用于存放镜像的,有点类似于maven仓库。用于集中管理镜像文件。

常用命令


镜像相关命令

以运行Python容器为例:

docker search python       #搜索Python镜像  
docker pull python:3.8.2   #拉取Python3.8.2的镜像 
docker images              #查看本地镜像列表,找到 Python 对应的 IMAGE ID。
docker images python       #列出名称未python的所有镜像
docker image ls            #执行效果好像与”docker images“相同,没有具体研究过差异 
docker history [imageId]   #查看镜像创建历史  


run命令

如下 “b5b4d78bc90c” 为我电脑中Python的 imageId。
可以执行 “docker images python” 找到 imageId 。

docker run -it b5b4d78bc90c /bin/bash #用镜像启动一个容器,并且直接进入该容器:输入"exit"退出容器后容器进程也停止,使用“docker ps -a”可以查看该容器运行状态为Exited。
docker run -itd b5b4d78bc90c /bin/bash  #使用镜像启动一个容器,并在后台执行,通过"docker ps -a"查看"containerId",然后通过"docker exec -it [containerId] bash"进入该容器,执行"exit"退出容器后该容器进程不退出,任然在后台运行。
docker run -itd --name py3.8 b5b4d78bc90c /bin/bash  #使用镜像启动一个容器,指定容器名称,并在后台执行,"--name py3.8" 表示指定容器名称,名称和containerId一样是唯一识别符不能重复,因为也可以通过容containerName进入容器"docker exec -it py3.8 bash"。 

docker run -v /opt/docker_container/python:/data  -w /data --name py3.8.2 -itd b5b4d78bc90c /bin/bash 
#在本地建立目录 /opt/docker_container/python 映射给容器的 /data 目录,并已/data为容器的工作目录 
#-v参数:映射本地文件启动容器
#-w参数:指定进入容器的工作目录,相当于进入容器自动执行"cd"命令 
#执行完后,可以通过 "docker ps -a" 看到一个正在运行的容器ID。

通过运行python文件

docker run -v $PWD:/usr/code/py -w /usr/code/py [pythonImageId] python hello.py  
#-v $PWD/myapp:/usr/src/myapp: 将主机中当前目录下的 myapp 挂载到容器的 /usr/src/myapp。hello.py文件在该目录中。
#-w /usr/src/myapp: 指定容器的 /usr/src/myapp 目录为工作目录。
#python helloworld.py: 使用容器的 python 命令来执行工作目录中的 helloworld.py 文件。
#执行完后,可以通过 "docker ps -a" 看到一个已经退出的容器ID。

启动mongodb容器

#参数指定数据的目录,数据库的用户名和密码等 
docker run --name mongo -p 27017:27017 -v ~/docker-data/mongo:/data/db -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=admin -d mongo


exec命令

通过containerId或者containerName进入容器bash

docker exec -it [containerId] bash     #通过containerId进入容器,然后执行bash交互式命令  
docker exec -it [containerName] bash   #进入containerName进入容器,然后执行bash交互式命令  

#容器bash即交互式的命令行,其实就是一个Linux的shell环境。
#containerID和containerName可以通过 “docker ps -a” 命令找到。
#-i 表示输入流(标准输入和错误输入——stdIn和errorIn),如果没有-i则不会输出任何内容,比如执行"ls"之后不会有任何输出。 
#-t 表示分配一个伪终端。  

通过容器执行脚本

docker exec [containId] /test.sh     #用容器执行脚本
docker exec -d [containId] /test.sh  #用容器执行脚本,

#-d 表示在后台执行,如果脚本执行时间过长,可以使用"-d"在后台运行。 

通过容器执行命令行

docker exec -it py3.8.2 bash -c "echo hello"               #进入容器执行echo命令,然后退出。  
docker exec -it py3.8.2 bash -c "echo hello && echo world" #连续执行多条命令,然后退出,命令之间用“&&”隔开。  
docker exec -it py3.8.2 bash -c "python main.py"           #进入容器执行python脚本,然后退出。  
docker exec -it py3.8.2 bash -c "echo 'print('\"'\"'hello python!'\"'\"')' > hello.py"  #执行echo并将结果输出到hello.py文件  

#“py3.8.2”是我本机的python容器名称。
#-c参数表示执行命令行,后面用双引号将命令行内容引起来,如 -c "echo hello"。
####题外话:
#注意后面命令行中的 [ \" ]是双引号转义,避免与最外层的双引号冲突,而'"'"'是为了让echo能输出单引号。 
#如 [ echo 'I'"'"'m' ] 能够正常输出为:I'm 
#其实这里分为了三段:用单引号引起来的字母I——['I'] 、用双引号引起来的单引号——["'"] ,以及用单引号引起来的字母m——['m']
#如  [ echo 'I'm' ] 和 [ echo I'm ] 都不能正确输出。
#说明:echo 后面输出的内容加双引号和不加是一样的, 
#如[ echo $PATH ] 和 [ ehco "$PATH" ] 都会输出变量PATH的具体值,
#而单引号则表示原样输出,如 [ echo '$PATH' ] 则输出为“$PATH”字符本身。


top命令

docker top [containerId|containerName] #查看容器内部的进程 

#如:
docker top 894ddc4c6dd1
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                13077               13037               0                   16:38               pts/0               00:00:00            /bin/bash
root                14619               13037               0                   16:57               ?                   00:00:00            /bin/bash
root                14627               14619               0                   16:57               ?                   00:00:00            python

#当然你也可以先进入容器bash:”docker exec -it 894ddc4c6dd1 bash“,然后再执行”top“。 
#不过容器中还不一定有top命令,这时可以使用”docker top“来直接查看容器中正在运行的进程。


容器启动和停止

docker start [containerId|containerName]    #启动容器 
docker restart [containerId|containerName]  #重启容器 
docker stop  [containerId|containerName]    #停止容器,”优雅停止“——让容器自己停止,在停止前可能有一些”退出前“的工作需要做,比如等待一些未执行完的请求等。
docker kill [containerId|containerName]     #强制停止容器,杀掉一个运行中的容器进程  
docker pause [containerId|containerName]    #暂停容器
docker unpause [containerId|containerName]  #恢复容器 


彻底删除镜像

#先停止容器,然后删除容器,最后删除镜像    
docker stop [containerId] #停止容器,通过 docker ps -a 找到container_id
docker rm [containerId]   #删除容器,通过 docker ps -a 找到container_id
docker rmi [imageId]      #删除镜像,通过 docker images 找到image_id


其他命令

docker create [imageId|imageName]  #创建一个新的容器但不启动它

#与run命令相比较:
#不同点:run命令根据镜像创建容器,并启动它,而create只创建不启动。
#共同点:如果后面的参数是imageName,而不是imageId,则本地不存在该镜像时,会从仓库pull该镜像。 

docker -v        #查看版本号
docker version   #查看详细的版本信息,包括docker版本以及api版本等
docker info      #查看docker系统信息,包括镜像和容器数等 

docker ps               #查看正在运行的容器  
docker ps -a            #查看容器列表,包含当前运行的和曾经运行过的  
docker container ls     #查看容器列表,同 “ps” 命令  
docker container ls  -a #查看容器列表,同 “ps -a” 命令 

docker inspect [containerId|containerName] #列出容器的详细信息(json格式展示)
 
docker attach [containerId|containerName]  
#attach到容器,看似效果与 “docker exec -it [containerId] bash” 类似,
#但是他们功能不同,attach相当于与宿主机器共享屏幕(共享终端),宿主机器指运行docker的机器,
#而 “docker exec -it” 是分配一个伪终端给到宿主机器,有点类似于ssh远程连接。 
#在“attach共享终端”中执行exit退出后,容器也会退出,执行 “docker ps -a” 可以看到该容器状态已经exited。  

说明:
上面命令中的 containerId 可以换成 containerName ,执行效果一样。
docker ps -a 可以列出 containerId 和 containerName
在容器bash环境中执行 exit 退出容器。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章