docker是什么?
首先我们可以把他当成虚拟机管理工具(例如virtualbox),我们来看看一些概念:
- 镜像:等同于虚拟机的镜像
- 容器:等同于虚拟机实例
- 容器卷:等同于磁盘
- 网络: 等同于虚拟机的网络
快速开始
- 安装(基于centos7,版本为1.13)
yum -y install docker
- 启动服务
systemctl start docker
- 拉取一个镜像
docker pull nginx
- 启动一个容器(并且映射容器里面的80端口到宿主机8080端口)
docker run -d -p 8080:80 nginx
镜像相关操作
对于镜像管理,我们一般就是搜索,下载,删除,查看
- 搜索镜像
docker search 关键字
- 下载镜像
docker pull 镜像名字
# 或者带上版本
docker pull 镜像名字:版本
- 查看本机的已经下载的镜像列表
docker images
- 删除一个镜像
docker rmi 镜像ID
容器相关管理
对容器的管理,常用的有创建,停止,启动,删除
- 创建
创建容器的命令可选参数非常多,我们先看最简单的一条命令
docker run -d nginx
映射容器的80端口到宿主机8080端口
docker run -d -p 8080:80 nginx
容器退出的时候删除容器
docker run -d --rm nginx
挂载宿主机目录/a到容器目录/b
docker run -d -v /a:/b nginx
限制容器cpu权重为5(默认是1024),内存256M
docker run -d -c 5 -m 256M nginx
- 查看正在运行的容器
docker ps
- 查看所有容器(包含运行和停止)
docker ps -a
- 启动一个停止了的容器
docker start 容器id
- 停止一个容器
docker stop 容器id
- 删除一个容器
docker rm 容器id
制作一个镜像
很多时候,现有的镜像并不能满足自己的需求,往往要自定义一个镜像。制作镜像有两种方法,一种是把一个容器打包成一个镜像。
docker commit -m "描述" -a "作者名字" 容器ID 镜像名字
另一种就是通过Dockerfile文件
我们来看一下一个Dockerfile文件有什么内容,首先它是一个文本文件,名字就是Dockerfile,里面填写构建命令,#开头是注释。
构建镜像的时候
docker build -t 镜像名字 .
# python环境,v1, nginx, python2.7
FROM centos:7
MAINTAINER yubang([email protected])
RUN yum install epel-release -y
RUN yum install nginx -y
RUN yum -y install mysql-devel
RUN yum install python2-pip -y
RUN mkdir -v ~/.pip && echo -e "[global]\ntimeout = 60\nindex-url = https://pypi.douban.com/simple" > ~/.pip/pip.conf
RUN pip install gunicorn
RUN pip install gevent
ADD nginx.conf /etc/nginx/nginx.conf
ADD install.sh /var/install.sh
ADD start.sh /var/start.sh
下面给出指令的作用说明:
- FROM 镜像名字:表示基于某个镜像构建
- RUN 命令:表示执行命令
- COPY 宿主机路径 容器路径:复制文件到镜像
- ADD 源文件路径 容器路径:复制文件到镜像,但是可以远程下载, gzip , bzip2 以及 xz还会自动解压
- cmd 命令:表示容器启动时候默认使用的命令
# 实质是 sh -c echo abc
CMD echo abc
#
CMD ["sh", "-c", "echo", "abc"]
- ENV : 设置环境标量(两种模式)
ENV k v
ENV k=v k2=v2
- ARG:仅仅存在构建过程中的环境变量
ARG k=v
- VOLUME:定义匿名容器卷
VOLUME ["位置1", "位置2"]
VOLUME 位置1
- EXPOSE:暴露端口
EXPOSE 端口1 端口2
- WORKDIR 目录:默认的工作目录
- USER 用户名:以某个用户运行
- HEALTHCHECK :健康检查命令,interval为检测间隔时间,默认30秒。timeout为检查默认超时时间,默认30秒。retries为重试次数,默认3次为unhealthy
HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://localhost/ || exit 1
容器编排
我们来看一个场景,我们需要在一台服务器上运行若干个容器。某一天我们需要在另一台服务器跑同样的容器咋办呢?
方案一:写一个shell脚本
方案二:基于Docker Compose
我们主要来瞧一瞧方案二,它需要我们编写一个docker-compose.yml文件,该文件是一个yaml格式的文本文件。然后我们就可以定义容器的各种规则。
我们来看一看官方提供的例子:
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
使用的是版本3,然后生成两个容器,其中一个容器端口映射,也挂载宿主机目录到容器里面
指令详解:
- build:后面跟着Dockerfile路径,用于构建一个镜像,然后如果有image参数,则生成的镜像名字为image指定的值。build也可以是一个对象,如:( context可以是git仓库地址)
build:
context: ./ownDir
dockerfile: Dockerfile
args:
- a: b
- image: 基于哪个镜像启动
- container_name: 指定生成的容器名字
- volumes: 挂载容器卷
- command: 容器启动执行的命令
- links: 链接哪个容器,使用别名
- external_links: 链接到非Docker Compose管理的容器
- expose:暴露端口
- ports:映射端口
- restart:容器重启策略,no是任何情况都不重启容器。always是总是重启容器。on-failure是出故障了才会重启容器。
- environment:设置环境变量,可以用字典也可以用数组
environment:
k: v
environment:
- k=v
- pid:是否与主机共享进程pid
pid: "host"
- dns:配置dns服务器
dns: 8.8.8.8
dns:
- 8.8.8.8
- labels:添加标签数据
labels:
k: v
labels:
- "k v"
常用命令(来自官网)
Define and run multi-container applications with Docker.
Usage:
docker-compose [-f ...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
Options:
-f, --file FILE Specify an alternate compose file
(default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name
(default: directory name)
--verbose Show more output
--log-level LEVEL Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
--no-ansi Do not print ANSI control characters
-v, --version Print version and exit
-H, --host HOST Daemon socket to connect to
--tls Use TLS; implied by --tlsverify
--tlscacert CA_PATH Trust certs signed only by this CA
--tlscert CLIENT_CERT_PATH Path to TLS certificate file
--tlskey TLS_KEY_PATH Path to TLS key file
--tlsverify Use TLS and verify the remote
--skip-hostname-check Don't check the daemon's hostname against the
name specified in the client certificate
--project-directory PATH Specify an alternate working directory
(default: the path of the Compose file)
--compatibility If set, Compose will attempt to convert deploy
keys in v3 files to their non-Swarm equivalent
Commands:
build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the Compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information
docker swarm
上面说到容器编排,让我们运行容器很方便。但是有一个明显的缺点,就是没办法跨主机运行。这个时候我们就需要docker swarm来构建docker 容器集群了。
使用docker swarm首先要创建一个集群(下面命令还会输出让其它服务器加入子节点的命令)
docker swarm init --advertise-addr {本机地址}
然后可以配置若干个子节点
- 创建一个服务
docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]
- 查看一个服务
docker service inspect [OPTIONS] SERVICE [SERVICE...]
- 查看服务日志
docker service logs [OPTIONS] SERVICE
- 查看服务列表
docker service ls [OPTIONS]
- 查看task
docker service ps [OPTIONS] SERVICE
- 查看服务里面的task
docker service ps [OPTIONS] SERVICE
- 删除一个服务
docker service rm SERVICE [SERVICE...]
- 修改服务的容器实例数量
docker service scale SERVICE=REPLICAS [SERVICE=REPLICAS...]
- 更新服务
docker service update [OPTIONS] SERVICE
docker维护
当使用时间旧了之后,我们会残留很多废弃的容器,镜像,容器卷等在服务器。在1.13之前,我们只能手动编写脚本清除。但1.13开始,docker提供清除无用的镜像,容器,容器卷,网络的命令。
# 清除没有依赖的镜像和停止运行的容器,没有使用的容器卷与网络(强制清除用-f)
docker system prune
# 清除没有依赖的镜像(强制清除用-f)
docker image prune
# 清除停止运行的容器(强制清除用-f)
docker container prune
# 清除没有使用的网络(强制清除用-f)
docker network prune
# 清除没有使用的容器卷(强制清除用-f)
docker volume prune
docker 的工作原理
为了更好地使用docker,我们还是需要了解一下docker是如何实现的。
首先docker里面运行的进程其实只是基于namespaces来隔离的,所以容器里面看不到宿主机其它进程,但是宿主机可以看到容器里面的进程。
同理,docker网络的实现也是基于命名空间实现了隔离。
而docker容器限制资源的消耗(包括CPU,内存,磁盘IO)则基于CGroup 。
然后文件系统的隔离其实基于chroot切换系统的根目录,这样子就能避免读到宿主机整个目录。
然后通过存储驱动(例如AUFS)实现镜像的存储。