docker实践(1) 入门和springBoot实践部署》

docker实践(2)常用命令和DockerFile详解》

docker实践(3) 仓库registry和Nexus3作为私有镜像仓库》

一. 常用命令:docker client操作


镜像相关命令

1、获取:docker pull centos获取镜像 官方仓库注册服务器下载镜像

   docker pull dl.dockerpool.com:5000/ubuntu:12.04 指定完整的仓库注册服务器地址下载镜像。

   docker search centos #搜索官方仓库注册服务器下的centos镜像   

2、列出本地镜像: docker images :REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE  

REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
   java8                   latest              98da345fd9e5        32 hours ago        557.4 MB
   docker.io/centos        latest              36540f359ca3        11 days ago         192.5 MB

3、提交镜像到本地:docker commit -m "message"  ImageID  tag 提交更新镜像后的副本
4、导出镜像:

docker save -o cenos7.3.tar centos  #导出镜像到本地文件 cenos7.3.tar
     docker save <myimage>:<tag> | gzip > <myimage>_<tag>.tar.gz

5、导入镜像:

cenos7.3.tar  #docker load -i  cenos7.3.tar 
     #或者 docker load < centos7.3.tar
    #

8、移除本地docker rmi <image_id> 

 *注意: docker rm 命令是移除容器。

  *注意:在删除镜像之前要先用 docker rm 删掉依赖于这个镜像的所有容器。

容器运行命令  

1、运行镜像:

Docker run 命令基本结构:

docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
 
 
常用选项说明
 -d, --detach=false, 指定容器运行于前台还是后台,默认为false
 -i, --interactive=false, 打开STDIN,用于控制台交互
-t, --tty=false, 分配tty设备,该可以支持终端登录,默认为false
 -u, --user="", 指定容器的用户
 -a, --attach=[], 登录容器(必须是以docker run -d启动的容器)
 -w, --workdir="", 指定容器的工作目录
 -c, --cpu-shares=0, 设置容器CPU权重,在CPU共享场景使用
 -e, --env=[], 指定环境变量,容器中可以使用该环境变量
 -m, --memory="", 指定容器的内存上限
 -P, --publish-all=false, 指定容器暴露的端口
 -p, --publish=[], 指定容器暴露的端口
 -h, --hostname="", 指定容器的主机名
 -v, --volume=[], 给容器挂载存储卷,挂载到容器的某个目录
 --volumes-from=[], 给容器挂载其他容器上的卷,挂载到容器的某个目录
 --cap-add=[], 添加权限,权限清单详见:http://linux.die.net/man/7/capabilities
 --cap-drop=[], 删除权限,权限清单详见:http://linux.die.net/man/7/capabilities
 --cidfile="", 运行容器后,在指定文件中写入容器PID值,一种典型的监控系统用法
--cpuset="", 设置容器可以使用哪些CPU,此参数可以用来容器独占CPU
 --device=[], 添加主机设备给容器,相当于设备直通
 --dns=[], 指定容器的dns服务器
 --dns-search=[], 指定容器的dns搜索域名,写入到容器的/etc/resolv.conf文件
 --entrypoint="", 覆盖image的入口点
 --env-file=[], 指定环境变量文件,文件格式为每行一个环境变量
 --expose=[], 指定容器暴露的端口,即修改镜像的暴露端口
 --link=[], 指定容器间的关联,使用其他容器的IP、env等信息
 --lxc-conf=[], 指定容器的配置文件,只有在指定--exec-driver=lxc时使用
--name="", 指定容器名字,后续可以通过名字进行容器管理,links特性需要使用名字
 --net="bridge", 容器网络设置:
 bridge 使用docker daemon指定的网桥
 host //容器使用主机的网络
 container:NAME_or_ID >//使用其他容器的网路,共享IP和PORT等网络资源
 none 容器使用自己的网络(类似--net=bridge),但是不进行配置
 --privileged=false, 指定容器是否为特权容器,特权容器拥有所有的capabilities
 --restart="no", 指定容器停止后的重启策略:
 no:容器退出时不重启
 on-failure:容器故障退出(返回值非零)时重启
 always:容器退出时总是重启
 --rm=false, 指定容器停止后自动删除容器(不支持以docker run -d启动的容器)
 --sig-proxy=true, 设置由代理接受并处理信号,但是SIGCHLD、SIGSTOP和SIGKILL不能被代理
docker run centos  /bin/echo 'Hello world': 输出一个 “Hello World”, 之后终止容器。跟在本地直接执行 echo 'hello world' 几乎感觉不出任何区别。

        docker run -t -i centos  /bin/bash:启动一个bash 终端, 允许用户进行交互:

 -t 选项让Docker分配一个伪终端( pseudo-tty) 并绑定到容器的标准输入上,

  -i 则让容器的标准输入保持打开。

         在交互模式下, 用户可以通过所创建的终端来输入命令。

      当利用 docker run 来创建容器时, Docker 在后台运行的标准操作包括:

      1)检查本地是否存在指定的镜像, 不存在就从公有仓库下载

      2)利用镜像创建并启动一个容器

      3)分配一个文件系统, 并在只读的镜像层外面挂载一层可读写层

      4)从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去

      5)从地址池配置一个 ip 地址给容器

      6)执行用户指定的应用程序

      7)执行完毕后容器被终止

    

2、守护运行:docker run centos -d  /bin/echo 'Hello world'

     运行状态:docker ps -a

3、端口映射:  docker run centos -d  -p 80:8080 springboot :本地0.0.0.0:80端口映射到容器的0.0.0.0:8080端口

     映射指定ip:docker run -d -p 127.0.0.1:80:8080 training/webapp python app.py

4、自定义容器名称:启动容器的时候, 系统默认会分配一个名字,使用 --name 标记可以为容器自定义命名。
   docker run -d -P --name web training/webapp python app.py
   注意:容器的名称是唯一的。 如果已经命名了一个叫 web 的容器, 当你要再次使用 web 这个名称的时候,需要先用 docker rm 来删除之前创建的同名容器。
6、docker inspect  <container name> 显示更底层的容器或image信息

7、查看容器日志:docker logs centos 

8、启动容器:docker start centos ,

9、终止容器:docker stop centos 来终止一个运行中的容器。
   
   注意:当Docker容器中指定的应用终结时, 容器也自动终止,终止状态的容器可以用 docker ps -a 命令看到。

    1) 例如只启动了一个终端的容器:docker run -t -i centos  /bin/bash  .用户通过 exit 命令或 Ctrl+d 来退出终端时, 所创建的容器立刻终止。

另外系统镜像默认启动是bash,如果没有衔接输入流,本身就会马上结束。

        例如Dockerfile最后的命令后面带有&

#基础镜像:仓库是java,标签用java8 
FROM java8  
#当前镜像的维护者和联系方式  
MAINTAINER guisu guisu@example.com  
#将打包好的spring程序拷贝到容器中的指定位置  
ADD CityData-0.0.1-SNAPSHOT.jar /opt/CityData-0.0.1-SNAPSHOT.jar  
#容器对外暴露8080端口  
EXPOSE 8080  
#容器启动后需要执行的命令  
CMD $JAVA_HOME/bin/java  -jar /opt/CityData-0.0.1-SNAPSHOT.jar  &

启动容器后就会退出。

10、重启容器:docker restar<tag> :将一个运行态的容器终止, 然后再重新启动它。

11、导出容器快照:docker export <CONTAINER id > centos.tar  

12、导入容器快照:cat centos.tar | sudo docker import - test/centos:v1.0

    可以通过指定 URL 或者某个目录来导入, 例如
   $docker import http://example.com/exampleimage.tgz example/imagerepo

*注:用户既可以使用 docker load 来导入镜像存储文件到本地镜像库, 也可以使用 docker import 来导入一个容器快照到本地镜像库。 这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息( 即仅保存容器当时的快照状态) , 而镜像存储文件将保存完整记录, 体积也要大。 此外, 从容器快照文件导入时可以重新指定标签等元数据信息。

13、删除容器:docker rm centos  #来删除一个处于终止状态的容器centos。
     docker rm -f centos  强制删除容器,不管是运行还是终止状态容器

进入容器管理 

3、进入容器管理 

进入容器的方法主要有以下几种: 
1. 使用ssh登陆进容器 
2. 使用nsenter、nsinit等第三方工具 
3. 使用docker本身提供的工具

方法1 :需要在容器中启动sshd,存在开销和攻击面增大的问题。同时也违反了Docker所倡导 的一个容器一个进程的原则。 
方法2:需要额外学习使用第三方工具。 
所以大多数情况最好还是使用Docker原生方法,Docker目前主要提供了Docker exec和 Docker attach两个命令。

docker attach

docker attach < container id >  或者 Docker attach <container name > 

Docker attach可以attach到一个已经运行的容器的stdin,然后进行命令执行的动作。 

**注意:如果从这个标准输入stdin中exit或者Ctrl +C,会导致容器的停止。

[root@iZ235fz06auZ java8]# docker ps 
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS               NAMES
3473c923443d        nlp-chitchat-data-api   "/bin/sh -c '$JAVA_HO"   7 seconds ago       Up 6 seconds        8080/tcp            serene_bartik                   bb2
[root@localhost temp]# docker attach  serene_bartik
/ # pwd
/
/ #

docker exec

docker exec   -it  <container name >   /bin/bash

或者docker exec -it <container name >  /bin/sh

关于-i、-t参数

可以看出只用-i时,由于没有分配伪终端,看起来像pipe执行一样。但是执行结果、命令 返回值都可以正确获取。

[root@iZ235fz06auZ java8]#  docker exec -i 0638203e2f89 /bin/bash
date
Mon Jul 17 03:25:51 UTC 2017

使用-it时,则和我们平常操作console界面类似。而且也不会像attach方式因为退出,导致 整个容器退出。 
这种方式可以替代ssh或者nsenter、nsinit方式,在容器内进行操作。

[root@localhost temp]# docker exec -it 0638203e2f89  /bin/sh
/ # pwd
/
/ # echo $?
0
/ # dir
/bin/sh: dir: not found
/ # echo $?
127

如果只使用-t参数,则可以看到一个console窗口,但是执行命令会发现由于没有获得stdin 的输出,无法看到命令执行情况。

docker exec执行后,会命令执行返回值。(备注Docker1.3似乎有Bug,不能正确返回命令执行结果)

[root@localhost temp]# docker exec -it bb cat /a.sh
echo "running a.sh"
exit 10
[root@localhost temp]# docker exec -t bb /a.sh
running a.sh
[root@localhost temp]# echo $?
10
[root@localhost temp]# docker exec -it bb /a.sh
running a.sh
[root@localhost temp]# echo $?
10
[root@localhost temp]# docker exec -i bb /a.sh
running a.sh
[root@localhost temp]# echo $?
10

关于-d参数

在后台执行一个进程。可以看出,如果一个命令需要长时间进程,使用-d参数会很快返回。 程序在后台运行。

[root@localhost temp]# docker exec -d bb2 /a.sh
[root@localhost temp]# echo $?
0

如果不使用-d参数,由于命令需要长时间执行,docker exec会卡住,一直等命令执行完成 
才返回。

# docker exec  bb2 /a.sh
#
# docker exec -it  bb2 /a.sh
#
# docker exec -i  bb2 /a.sh
# docker exec -t  bb2 /a.sh
#

 二、使用docker api操作


docker客户端可以使用docker engine api来操作和管理docker。docker api文档:https://docs.docker.com/engine/api/v1.41/#

官方SDK目前只有go和python版本,无其他语言的SDK,官方建议直接使用api

非官方java语言版本可以使用:GitHub - docker-java/docker-java: Java Docker API Client

还有个参考文档:Getting started with Java | Docker Documentation

1、创建

curl -X POST -H "Content-Type: application/json" -d '{
     "Image":"docker-reg.xxx.com/tlinux/tlinux3.2:v118",
     "Tty":true,
     "OpenStdin":true,
     "HostConfig":{
         "Binds":[
             "/sys/fs/cgroup:/sys/fs/cgroup:ro",
             "/search/odin/container11.162.8.18_coredata:/coredata",
             "/search/odin/container11.162.8.18_data:/search/odin",
             "/etc/11.162.8.18:/etc/sn"
         ],
         "CpusetCpus":"2-131",
         "CpusetMems":"1",
         "NetworkMode":"vcnet",
         "RestartPolicy":{
             "Name":"always",
             "MaximumRetryCount":0
         },
         "SecurityOpt":[
             "seccomp=unconfined",
             "label=disable"
         ],
         "Tmpfs":{
             "/run":"rw"
         },
         "Privileged":false,
         "CapAdd":[
             "CAP_SYS_RESOURCE",
             "SYS_ADMIN",
             "CAP_SYS_NICE",
             "CAP_IPC_LOCK"
         ]
     },
     "NetworkingConfig":{
         "EndpointsConfig":{
             "vcnet":{
                 "IPAMConfig":{
                     "IPv4Address":"11.162.8.18"
                 }
             }
         }
     }
 }' https://11.162.0.10:2376/containers/create?name=container2 --cert /usr/local/dockercert/cert.pem --key /usr/local/dockercert/key.pem --cacert  /usr/local/dockercert/ca.pemcpu超限提示错误:
HTTP/1.1 400 Bad Request
 Api-Version: 1.40
 Content-Type: application/json
 Docker-Experimental: false
 Ostype: linux
 Server: Docker/19.03.6 (linux)
 Date: Thu, 07 Sep 2023 06:17:09 GMT
 Content-Length: 87{"message":"Range of CPUs is from 0.01 to 48.00, as there are only 48 CPUs available"}

2、执行命令:

curl -X POST -H "Content-Type: application/json" -d '{
   "AttachStdin": false,
   "AttachStdout": true,
   "AttachStderr": true,
   "Cmd": ["sh", "-c", "ls /"]
 } ' https://11.162.64.8:2376/containers/4639b165302e48c89da018e44814b0d0/exec --cert /search/odin/app/roc-iaas/iaas-jar/BOOT-INF/classes/tls/prd/cert.pem --key /search/odin/app/roc-iaas/iaas-jar/BOOT-INF/classes/tls/prd/key.pem --cacert  /search/odin/app/roc-iaas/iaas-jar/BOOT-INF/classes/tls/prd/ca.pem 返回结果:{"Id":"b42ade1b73938c2eabb9dcf10796b0871b5cd6c7a4de6acaf9d6141d1b78866e"}
使用这个id来启动命令:
curl -X POST -H "Content-Type: application/json" -d '{
  "Detach": false,
  "Tty": true
 } ' https://11.162.64.8:2376/exec/b42ade1b73938c2eabb9dcf10796b0871b5cd6c7a4de6acaf9d6141d1b78866e/start --cert /search/odin/app/roc-iaas/iaas-jar/BOOT-INF/classes/tls/prd/cert.pem --key /search/odin/app/roc-iaas/iaas-jar/BOOT-INF/classes/tls/prd/key.pem --cacert  /search/odin/app/roc-iaas/iaas-jar/BOOT-INF/classes/tls/prd/ca.pem