author

koly

docker基础

学习docker,既然学习了,那么自然需要有输出。这篇就算学习笔记了。先看看一些基础知识。

docker是什么?

一个工具,这个工具可以帮助你创建一个虚拟机。然后你可以对这个虚拟机环境进行各种配置。既然建立了虚拟机,就可以实现对虚拟机的管理,比如start,restart,stop等。还可以把这些虚拟机怎么建立的发布在网上,让大家都可以用。比如你想要一台java环境的ubuntu,以前你需要自己搞一个虚拟机,然后在里面安装java,然后配置网络映射。现在就只需要使用docker,然后用一个命令,就可以拿到已经安装了java的ubuntu,然后起一个虚拟机,同时映射网络。

docker中的概念

  • docker engine,负责在系统中安装docker,创建和运行docker container。
  • image,相当于一个模板,虚拟机根据这个模板来进行配置。比如模板里面写了,要ubuntu,那就去下一个ubuntu,要tomcat,就去下一个,然后进行配置。每个image包含了多个layer。在创建image的时候,每一条指令都会创建一层layer,这些指令可以是:
    • 执行一个命令(RUN)
    • 添加一个文件或者目录
    • 创建一个环境变量
    • 指定container运行时执行的指令
      最终,多个layer会通过union file system被合并成为一个image。
  • container,这个是虚拟机的容器。就是说根据上面所说的image创建的虚拟机就跑在这里面。
  • docker hub,官方的下载各种image的地方。地址在这里:hub.docker.com
  • volume, 是一个mount point,就是可以给container指定一个volume,然后这个volume会跟host里面的某个地方(文件或者文件夹)映射起来。可以显示指定host里面对应的文件夹或文件,如果没有显示指定,那么docker会自动指定一个。
  • bridge,桥接。简单来说就是在host上建立一个网络,比如是叫isolated_net,然后可以指定container加入这个网络。这样就可以实现多个container的通信。默认情况下使用的网络是docker0。
  • docker-machine。一个工具。docker-machine可以在不同的地方创建docker host,比如在一台电脑上,在公有云或者私有云上。它会创建一个docker host,然后在上面安装docker,最后对docker client进行配置,使其可以访问docker host。同时,docker-machine还提供了一系列的命令来管理docker host。
  • docker registry。放docker image的地方。比如docker hub就是一个官方的public registry。当然可以搭建自己的private registry。

docker engine, docker machine, docker host和docker client

先来看看docker engine,官网是这样介绍的:

At the core of the Docker platform is Docker Engine, a lightweight runtime and robust tooling that builds and runs your Docker containers. Docker Engine runs on Linux to create the operating environment for your distributed applications. The in-host daemon communicates with the Docker client to execute commands to build, ship and run containers

https://www.docker.com/docker-engine

从上面那段文字,我们可以得到几点:

  • docker engine 是docker平台的核心部分
  • docker engine是一个轻量级的runtime,什么是runtime呢?就是可以让某些符合要求的东西运行的东西
  • docker engine同时还是一个工具,这个工具可以创建和运行docker container
  • docker engine运行在linux上,并且会为运行某些分布式程序创建环境。所以这就是说docker engine无法运行在mac和windows上咯?
  • docker host 里面运行的一个daemon会跟docker client通信,以此执行命令去创建,传输和运行container。
    docker engine还给了一张图:

docker engine

这个图告诉我们,docker engine会在os上面在创建一个环境。

先来看看docker在macOS上是怎么办的?
在docker mac上的安装文档里有说明,由于docker这个daemon,需要linux的kernel。所以docker没办法直接运行在MacOS上。所以需要先在Mac上创建一个虚拟机(Virtual Machine)咯。这个虚拟机还得是一个linux。这个虚拟机的创建就可以使用docker-machine。
在linux上,localhost就是docker host,也就是说Docker client, Docker daemon,以及containers都是直接运行在那台linux物理机上,而不是运行在虚拟机里。有个图:

docker_on_linux

同样的,在mac系统上也有一张图:

docker_on_mac

对比这两个图,就知道不同了。图里面还有一些概念:

  • docker client
  • docker host
  • docker daemon

那么,在MacOS上使用docker,需要做什么呢?

  • 创建一个virtual machine,然后在这个virtual machine里面安装一些东西。这时候就可以使用docker-machine create --driver virtualbox <machine_name>啦。
  • 然后告诉docker-machine,你要用这个新的docker vm啦:docker-machine env <machine_name>
  • 然后需要将shell同docker machine关联起来:eval "$(docker-machine env <machine_name>)"docker-machine env <machine_name>的结果是:
    1
    2
    3
    4
    5
    6
    export DOCKER_TLS_VERIFY="1"
    export DOCKER_HOST="tcp://192.168.99.101:2376"
    export DOCKER_CERT_PATH="/Users/mary/.docker/machine/machines/default"
    export DOCKER_MACHINE_NAME="default"
    # Run this command to configure your shell:
    # eval "$(docker-machine env default)"

eval就是把这些export …全部都在当前的shell执行一遍。我猜通过设置这些property,docker client就知道怎么去访问docker host了。顺便说一句刚刚建立的虚拟机是有一个自己的ip地址的。使用docker-machine ip <machine_name>可以得到该machine的ip,然后docker-machine ls可以列出所有的docker machine。

由于docker是可以直接运行在linux上的,所以linux上不需要创建虚拟机,所以在linux上,默认情况下,不需要使用docker-machine。所以玩docker还是找个linux distribution吧。

那么在linux上需要安装什么呢?

1
apt-get install docker-engine

docker-engine就可以了。

总结一下,docker-engine是docker需要的执行环境以及一些工具,是基础。docker-machine是用来创建和管理docker vm或者说是docker环境的。Docker host指的就是运行docker的机器,linux上就是运行linux的物理机,windows和mac上是一个虚拟机。Docker daemon是docker host里面运行的一个docker相关的程序,这个程序会完成诸如contaienr管理之类的工作。Docker
client是在docker虚拟机外的一个客户端,可以独立运行在linux,mac,和windows上。用户通过docker client跟docker daemon通信,以此完成各种操作,比如image的创建,container的生成等。

docker官方还有一张图:

understand docker

怎么用?

需求 命令
查看系统信息 docker info
查看所有命令 docker -h
查看单个命令帮助文档 docker help
pull一个image docker pull
创建image docker build
列出image docker images
删除image docker rmi
删除所有image docker rmi $(docker ps -aq)
创建container docker run
列出正在运行的container docker ps
列出所有的container docker ps -a
删除container docker rm
删除所有container docker rm $(docker images -q)
start container docker start
restart container docker restart
stop container docker stop
signal kill container docker kill
在某个container执行命令 docker exec -it
查看webapp的log docker logs -f
查看映射的端口 docker port
查看container的进程 docker top
inspect network docker network inspect [OPTIONS] NETWORK
create network docker network create –driver bridge
list network docker network ls
———————— ————————

使用container_id的地方也可以使用container_name。

创建image

创建一个image,就是创建一个模板,里面定义了这个image包含了哪些内容。这个模板叫做Dockerfile。有了Dockerfile之后,就可以通过命令docker build <directory that contains Dockerfile>来生成image了。这个过程就是根据Dockerfile来执行各种操作。下面是一个Nginx的Dockerfile:

1
2
3
4
5
6
7
8
9
10
11
FROM debian:jessie
MAINTAINER koly li <kolyjjj@foxmail.com>
ADD ./nginx_signing.key /tmp/
RUN chmod 755 /tmp/nginx_signing.key
RUN apt-key add /tmp/nginx_signing.key
RUN echo "deb http://nginx.org/packages/debian/ jessie nginx" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y curl vim nginx && apt-get clean && rm -rf /var/lib/apt/lists/*
RUN mkdir -p /var/www/html
# backup the default.conf file
RUN mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf_bac
ADD global.conf /etc/nginx/conf.d/

最前面的大写的是docker提供的命令,这里是docker file的文档。

坑和tips

  • 在mac电脑上使用docker时,会创建一个vbox的虚拟机,然后在这个虚拟机里面操作。在做docker nginx时,发现mount的volume,在host上改动之后,container里面的nginx无法及时发现改动。比如在host里面更新了index.html文件,但是更新的内容没有出现在浏览器里。google之后发现是一个virtual
    box的bug。github在这里。关于那个bug的讨论在这里
  • 在ubuntu里面使用docker,在debian:jessie里使用apt-get install tomcat7,结果启动container的时候发现stdout的输出表示启动tomcat没有成功,但是实际上tomcat却已经启动起来了。这里是关于这个issue的讨论。原因是tomcat的启动脚本需要一些权限,而docker container默认并没有这些权限。解决方案是在docker run的时候加上–cap-add
    SYS_PTRACE。或者–privileged=true。或者不使用apt-get install tomcat来安装。
  • docker-compose build,在mac上使用的时候,没有执行mysql的初始化脚本。简单来说,在使用mysql这个docker image的时候,可以将初始化的sql或者sh文件放在container的/docker-entrypoint-initdb.d这个文件夹下面,然后mysql这个image会在启动container的时候执行这些脚本,进行数据库的初始化。在mac上,使用docker build没有问题,但是使用docker-compose build却有问题。换到ubuntu上,都没有问题。解决方案就是使用ubuntu咯。
  • 如果使用docker run的时候带上-it参数,则可以使用Ctrl+c来结束container。
  • 在创建image时,原始镜像里面没有vi,那么可以使用sed来做文字的替换,比如将“daemonize no”替换为“daemonize yes”:set -i 's/daemonize no/daemonize yes/' /usr/local/redis/reids-3.0.6/redis.conf
  • 使用net而不是使用container link
  • debian:jessie这个image还是挺好用的,debian跟ubuntu的区别在于ubuntu加上了一个ui,然后各自的发布周期是不一样的。参照Ubuntu and Debian
  • 在写docker-compose.yml时,对每个service指定container_name
  • 将数据放在container的volume里,别的container如果要使用,在docker-compose.yml里用volumes_from

参考资料:
[1] docker官方文档