基础

容器相关

镜像相关

概念

Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。

docker是一个容器可以是一个虚拟的系统,并不一定是一个系统,比如一个docker容器可以只有1k大小(比如hello-world镜像),简单的只有一个脚本,执行完脚本docker自动关闭,当然容器中也可以是一个系统,这样可以对系统进行一些操作,部署项目,安装redis软件等,但是这样存在一个问题,如果一个服务器上既部署又有redis数据库等,那这个服务器需要安装n个docker容器,每个容器中安装一个软件,或者安装一个容器,其中安装所有的软件

ps-查看运行中的docker容器


docker ps
-  -a, --all             Show all containers (default shows just running)
-   -f, 
    -   --filter filter   Filter output based on conditions provided
    -   --format string   Pretty-print containers using a Go template
    -   --help            Print usage
-   -n, 
    -   --last int        Show n last created containers (includes all states) (default -1)
-   -l, 
    -   --latest          Show the latest created container (includes all states)
    -   --no-trunc        Don't truncate output
-   -q, 
    - --quiet           Only display numeric IDs
-   -s, 
    -   --size            Display total file sizes

logs-查看docker日志

docker logs -f kanche-bridge_kanche-bridge-v1_1

该命令可以查看启动的服务和停掉的服务的日志

假设 application 是 Docker容器内部运行的应用,
那么对于应用的第一部分标准输出(stdout)日志,
Docker Daemon 在运行这个容器时就会创建一个协程(goroutine),负责标准输出日志。<br/><br/>
由于此 goroutine 绑定了整个容器内所有进程的标准输出文件描述符,
因此容器内应用的所有标准输出日志,都会被 goroutine 接收。<br/><br/>
goroutine 接收到容器的标准输出内容时,立即将这部分内容,
写入与此容器—对应的日志文件中,
日志文件位于/var/lib/docker/containers/<container_id>,文件名为<container_id>-json.log。<br/><br/>
至此,关于容器内应用的所有标准输出日志信息,
已经全部被 Docker Daemon 接管,并重定向到与容器—对应的日志文件中。<br/><br/>
因此可以通过docker log或 查看物理机上的文件 两种方式查看日志

以下简要介绍 docker logs 命令下各参数的含义:

无参数:直接显示容器的所有日志信息
tail:从尾部开始按需显示容器日志
since:从某个时间开始显示容器日志
timestamp:显示容器日志时显示日志时间戳
f:将当前时间点,容器日志文件<container-id>-json.log中的日志信息全部打印;此时间点之后所有的日志信息与日志文件无关,直接接收goroutine往日志文件中写的文件描述符,并显示

exec-执行docker中的命令

docker exec -it kanche-bridge_kanche-bridge-v1_1 bash

version-查看docker的版本信息

docker version

images-查看本地镜像

docker images

镜像是对容器状态的保存

cp-复制文件

将容器中的某个文件复制到本地

docker cp kanche-bridge_kanche-bridge-v1_1:kanche-bridge.jar /tmp/

容器路径必须是绝对路径,否则只能cp0字节,即cp失败

docker cp kanche-bridge_kanche-bridge-v1_1:/opt/docker/kanche-bridge.jar /tmp/

docker search redis:
Search the Docker Hub for images

pull-从dockerhub上拉取镜像

liukaideMacBook-Pro:~ liukai$ docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
5b0f327be733: Pull complete 
Digest: sha256:1f1404e9ea1a6665e3664626c5d2cda76cf90a4df50cfee16aab1a78f58a3f95
Status: Downloaded newer image for hello-world:latest

若是私有镜像仓库,需要登录,具体参考login;可通过:指定版本号,如hello-world:1.0.0-test,若不指定则表示获取版本号为latest的镜像

create-从镜像创建容器

``` docker create -it ubuntu:latest ``` > 与run的区别在于,create创建后的容器是stop状态,需要通过docker start 命令启动

run-启动容器

通过docker run命令可以启动某一个镜像,并运行一个命令 `docker容器可以理解为在沙盒中运行的进程。这个沙盒包含了该进程运行所必须的资源,包括文件系统、系统类库、shell 环境等等。但这个沙盒默认是不会运行任何程序的。你需要在沙盒中运行一个进程来启动某一个容器。这个进程是该容器的唯一进程,所以当该进程结束的时候,容器也会完全的停止。`
  • docker run -i -t centos6.8
    这个容器一执行就会进入到默认的线程”/bin/bash”,直接进入控制台操作。当退出控制后后,容器会被终止
  • docker run -i -t -d centos6.8
    这个容器一执行,会自动执行默认的线程”/bin/bash”,但是不会让你马上进入控制台操作。将会在后台执行,用docker ps 可以看到当前运行的控制台。进入容器可是使用docker attach“container name or id” or docker exec *** bash。
  • docker run -d centos6.8 ping www.docker.com
    这个容器将永久在后台执行,因为ping这个线程不会停止。除非你停止了ping的线程。
  • [root@CentOS7.2 ~]#docker run -d --restart=always centos6.8 ping www.docker.com
    这个容器将永久在后台执行,因为ping这个线程不会停止。如果你把ping这个线程终止了,那么容器会重启继续执行ping功能
  • docker run -d --name=server-dbcentos6.8-mysql /usr/bin/mysql_safe -d

    这时候我们这个容器的名称为server-db,同时激活了数据库mysql的后台线程,让它不断的跑,这时候我们的容器也不会被关闭
  • docker run -d --name=server-http --link=server-db centos6.8-httpd /usr/bin/httpd --DFOREGROUND
    我们执行了apache的服务器让它不断的在后台执行,同时,在php里配置mysql的服务器名称为”server-db”,直接用server-db命名就可以了。不需要输入ip地址之类的。我们的server-http指定连接了server-db。server-db在server-http里会被当做一个DNS解析来获取相应的连接ip。 --link表示将该容器与另一个容器关联,即在该容器的hosts中添加另一个容器的配置;也可通过“echo 172.18.0.2 d85ab91161fd mysql >> hosts”向hosts写入内容
  • docker run -d --name=server-db -p 3306:3306 centos6.8-mysql /usr/bin/mysql_safe –d
    指定了服务器宿主机的3306端口映射到容器的3306端口,暴露出去。
  • docker run -d --name=server-http --link=server-db -p 8080:80centos6.8-httpd /usr/bin/httpd --DFOREGROUND
    指定了服务器宿主机的8080端口映射到容器80端口,暴露出去。
  • docker run -d --name=server-db -p 3306:3306 -v /server/mysql-data:/mysql-data centos6.8-mysql /usr/bin/mysql_safe –d
    将宿主机的数据库目录/server/mysql-data挂载到server-db上,你会发现,在server-db根目录下你会发现有一个新的文件夹mysql-data,同时里面的文件内容和宿主机下/server/mysql-data一样。
  • docker run -it --rm centos6.8
    我们进入了容器的控制台,当我们在容器内部exit退出控制台的时候,容器将被终止,同时自动删除。
  • docker run -t -i --rm --link db:db training/webapp /bin/bash
    • --rm表示容器终止后立刻删除
    • --link让容器之间安全的进行交互
    • --link name:alias: 其中name是要链接的容器名称;alias是这个连接的别名
    • --link进行的操作:1. 设置环境变量,如 端口等 2. 更新/etc/hosts文件,将欲连接的容器在本容器中设置hosts

run命令常用的参数


命令格式:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]   
Usage: docker run [OPTIONS] IMAGE [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 --name mysql_test_2 -e MYSQL_ROOT_PASSWORD=my-secret-pw -p 3307:3306 -id 5709795eeffa

rm-删除容器

rm 容器NAME :根据容器NAME删除对应的容器

rmi-删除镜像或tag

  • docker rmi imageid: 根据镜像id删除镜像;如果该id关联多个tag,则无法删除成功
  • docker rmi hello-world-test2:根据tag删除对应的镜像,如果该tag对应的镜像无其它关联tag,则删除该镜像,如果存在其它关联tag,则删除该tag

调用该命令删除镜像前需要确保该镜像对应的容器已全部删除,否则该镜像无法删除

start-启动停掉的容器

使用`docker ps -a`查看容器,发现存`Exited (0) 2 hours ago`状态的容器,使用`docker start name`启动容器 > name 为ps最后一个name字段,id无效果 可以使用 docker start name1 name2 name3 启动多个容器

stop-终止的容器

``` docker stop [-t | --time [=10]] ``` stop命令会向容器发送SIGTERM信号,等待一段时间后(默认为10s),再发送SIGKILL信号终止容器

kill-强行终止容器

直接发送SIGKILL信号强行终止容器

Dockerfile-文件格式

1. 概念

Dockerfile用来创建一个自定义的image,包含了用户指定的软件依赖等。

当前目录下包含Dockerfile,使用命令build来创建新的image,并命名为edwardsbean/centos6-jdk1.7:
docker build -t edwardsbean/centos6-jdk1.7 .

2. Dockerfile关键字

如何编写一个Dockerfile,格式如下:

  • FROM:基于哪个镜像,同一Dockerfile中创建多个镜像时,可使用多个FROM指定,但是每个镜像仅限一次

  • RUN:将对镜像执行跟随的命令。每运行一条RUN指令,镜像添加新的一层,并提交。

    • 格式为RUN [command]RUN ["EXECUTABLE","PARAM1","PARAM2"]
    • 前者将在shell终端中运行命令,即/bin/sh -c;
    • 后者则使用exec执行
    • 指定使用其他终端可以通过第二种方式实现,例如RUN ["/bin/bash","-c","echo hello"]
  • MAINTAINER:镜像创建者信息

  • CMD:container启动时执行的命令,但是一个Dockerfile中只能有一条CMD命令,多条则只执行最后一条CMD。CMD主要用于container时启动指定的服务,当docker run command的命令匹配到CMD command时,会替换CMD执行的命令。

    • CMD ["EXECUTABLE","PARAM1","PARAM2"]使用exec执行,推荐方式
    • CMD command param1 param2 在/bin/sh中执行,提供给需要交互的应用
    • CMD ["param1","param2"]提供给ENTRYPOINT的默认参数
例:CMD echo hello world
运行结果:<br/>
edwardsbean@ed-pc:~/software/docker-image/centos-add-test$ docker run centos-cmd<br/>
`hello world`</br>
一旦命令匹配:</br>
edwardsbean@ed-pc:~/software/docker-image/centos-add-test$ docker run centos-cmd echo hello edwardsbean<br/>
`hello edwardsbean`
  • ENTRYPOINT:container启动时执行的命令,但是一个Dockerfile中只能有一条ENTRYPOINT命令,如果多条,则只执行最后一条。ENTRYPOINT不可被docker run 提供的参数覆盖

    • ENTRYPOINT ["EXECUTABLE","PARAM1","PARAM2"]
    • ENTRYPOINT command param1 param2 (shell中执行)
  • USER:指定运行容器时的用户名或UID,后续的RUN也会使用指定用户
    如:

ENTRYPOINT ["memcached"]
USER daemon

  • EXPOSE:
    container内部服务开启的端口。
主机上要用还得在启动container时,做host-container的端口映射:
docker run -d -p 127.0.0.1:33301:22 centos6-ssh
container ssh服务的22端口被映射到主机的33301端口
  • ENV
    ENV [KEY] [VALUE]用来设置环境变量,比如:
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
  • ADD:将文件 src 拷贝到container的文件系统对应的路径 dest,所有拷贝到container中的文件和文件夹权限为0755,uid和gid为0,如果文件是可识别的压缩格式,则docker会自动解压为目录;也可以是一个URL
    • 如果要ADD本地文件,则本地文件必须在 docker build PATH,指定的PATH目录下
    • 如果要ADD远程文件,则远程文件必须在 docker build PATH,指定的PATH 目录下。比如:
      docker build github.com/creack/docker-firefox
      docker-firefox目录下必须有Dockerfile和要ADD的文件

注意:使用docker build - somefile 方式进行build,是不能直接将本地文件ADD到container中。只能ADD url file.
ADD只有在build镜像的时候运行一次,后面运行container的时候不会再重新加载了。

  • COPY: 复制本地主机的目录为容器中的目录,当目标路径不存在时,会自动创建;当使用本地目录为源目录时,推荐使用COPY
  • VOLUME:可以将本地文件夹或者其他container的文件夹挂载到container中。

  • WORKDIR:为后续的RUN,CMD,ENTRYPOINT指定配置工作目录,可使用多个WORKDIR指令

  • ONBUILD:ONBUILD配置当所创建的镜像作为其他新创建的基础镜像时,所执行的操作指令。

# 构建镜像image-a
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

# 当某镜像FROM image-a时,会自动执行ONBUILD指令内容,等价于在后面添加了两条指定

build-构建镜像

格式:
Usage: docker build [OPTIONS] PATH | URL | -

例子:
docker build -t imageName -f Dockerfile path

PATH:指定本地的路径,该路径为Dockerfile及Docker中操作文件的默认路径

- -f, --file string                Name of the Dockerfile (Default is 'PATH/Dockerfile')
- -t, --tag list                   Name and optionally a tag in the 'name:tag' format

commit-构建镜像

docker commit -m "comment" -a " author " imageId imageTag

inspect-查看容器的信息

docker inspect 容器名/容器id:查看容器的配置信息:容器名,环境变量, 运行命令, 主机配置,网络配置,数据卷配置。 比如 Mounts表示docker容器的挂载信息,若挂载了物理机,则部署新的docker 文件夹内容不会丢 > 该命令同样可查看镜像信息

export-导出容器

导出已经创建的容器到一个文件 docker export 7691a814370e > ubuntu.tar

import-导入容器

docker import 从容器快照文件中再导入为镜像 $ cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0

根据某url导入容器
docker import http://example.com/exampleimage.tgz example/imagerepo

save-存出镜像

# 将镜像 ubuntu:14.04 存出为文件 ubuntu_14.04.tar
docker save -o ubuntu_14.04.tar ubuntu:14.04

load-载入镜像

# 从本地文件中导入到本地镜像库
docker load --input ubuntu_14.04.tar
或
docker load < ubuntu_14.04.tar

docker load与docker import的区别:
容器快照文件将丢弃所有的历史记录和无数据信息(仅保存容器当时的快照状态)
而镜像存储文件将保存完整记录,体积也更大。
此外,从容器快照文件导入时可以重新指定标签等元数据信息

tag-对镜像设置标签

  • docker tag hello-world cnkevin/cnkevin-jre:1.0.0-test

tag用于标识镜像仓库,如果为dockerhub,则只需要user/image:tag 即可,若为个人仓库,则需要harbor.xxx.com/user/image:tagdocker push时根据tag上传至相应的镜像仓库

tag-对镜像设置标签

  • docker push cnkevin/cnkevin-jre:latest
unauthorized: authentication required
通过docker login命令登陆镜像仓库

login-登录镜像仓库

  • docker login harbor.xxx.com :登陆个人镜像仓库,若省略harbor.xxx.com则表示登陆dockerhub
  • docker login后会在~/.docker/下生成一个config.json保存docker登录信息
  1. docker tag必须将镜像文件打标为 harborurl/user/image的形式,push时会根据harborurl去.docker/config.json中查找用户登录信息,并推送镜像
  2. 如果向非hub.docker.com推送镜像 需要tag为 harbor.xxx.com/xxx/java-jre但是向dockerhub推送只需要tag为userid/image即可,但是前提是通过docker login登录docker hub,并且不可加任何地址,若加地址应为docker.io,而非hub.docker.com
> cat .docker/config.json
{
	"auths": {
		"harbor.xxx.com": {
			"auth": "YWRtaW46SGFyYm9yQFl4cWljaGUyMDE4IQ=="
		},
		"https://index.docker.io/v1/": {
			"auth": "Y25rZXZpbjprYWkxMjM0NTY="
		}
	}
}    

附1-容器与镜像的概念

  • 容器:虚拟机的概念,无论启动中还是关闭,均为容器
  • 镜像:将虚拟机的某个状态,保存为镜像,可根据镜像还原容器