Docker背景
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似手机app,一个容器就是一个app),更重要的是容器性能开销极低。
Docker可以实现的功能:
Web 应用的自动化打包和发布。
自动化测试和持续集成、发布。
在服务型环境中部署和调整数据库或其他的后台应用。
从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。
Docker的优点:
1、更快速的交付和部署
对开发和运维(devop)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。
开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。
2、更高效的虚拟化
Docker 容器的运行不需要额外的 hypervisor 支持,它是内核级的虚拟化,因此可以实现更高的性能和效率。
3、更轻松的迁移和扩展
Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。
4、更简单的管理
使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。
Docker架构
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
Docker 容器通过 Docker 镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。
架构中主要有两个概念:
Docker daemon: 运行在宿主机上,Docker守护进程,用户通过Docker client(Docker命令)与Docker daemon交互
Docker client: Docker 命令行工具,是用户使用Docker的主要方式,Docker client与Docker daemon通信并将结果返回给用户,Docker client也可以通过socket或者RESTful api访问远程的Docker daemon
Docker还有三个主要概念:
Docker image:镜像是只读的,镜像中包含有需要运行的文件。镜像用来创建container,一个镜像可以运行多个container;镜像可以通过Dockerfile创建,也可以从Docker hub/registry上下载。
Docker container:容器是Docker的运行组件,启动一个container就是一个容器,容器是一个隔离环境,多个容器之间不会相互影响,保证容器中的程序运行在一个相对安全的环境中。
Docker hub/registry: 共享和管理Docker镜像,用户可以上传或者下载上面的镜像,官方地址为https://registry.hub.docker.com/,也可以搭建自己私有的Docker registry。
我们通过客户端写命令,然后客户端将命令发送给守护进程,守护进程再将命令执行的结果返回给客户端,这就使我们能通过命令查看执行结果,镜像就是容器的源代码,容器通过镜像启动,使用仓库来保存用户构建的镜像,仓库分为共有和私有。
Docker安装
建议在linux环境下安装Docker,window环境搭建比较复杂且容易出错,使用Centos7+yum来安装Docker环境很方便。
yum install docker
安装完成后,使用下面的命令来启动 docker 服务,并将其设置为开机启动:
service docker start
chkconfig docker on
此处采用了旧式的 sysv 语法,如采用CentOS 7中支持的新式 systemd 语法,如下:
systemctl start docker.service
systemctl enable docker.service
测试
docker version
Ubuntu Docker 安装
Docker 支持以下的 Ubuntu 版本:
Ubuntu Precise 12.04 (LTS)
Ubuntu Trusty 14.04 (LTS)
Ubuntu Wily 15.10
其他更新的版本
安装:
~$ wget -qO- https://get.docker.com/ | sh
输入当前用户的密码后,就会下载脚本并且安装Docker及依赖包。
安装完成后有个提示:
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:
sudo usermod -aG docker runoob
Remember that you will have to log out and back in for this to take effect!
当要以非root用户可以直接运行docker时,需要执行 sudo usermod -aG docker runoob 命令,然后重新登陆,否则会有报错
启动docker后台服务
~$ sudo service docker start
测试运行hello-world
runoob@runoob:~$ docker run hello-world
镜像加速
鉴于国内网络问题,后续拉取 Docker 镜像十分缓慢,我们可以需要配置加速器来解决。
Docker 中国官方镜像加速可通过registry.docker-cn.com访问。该镜像库只包含流行的公有镜像,私有镜像仍需要从美国镜像库中拉取。
或者使用的网易的镜像地址:http://hub-mirror.c.163.com。
新版的 Docker 使用 /etc/docker/daemon.json(Linux) 或
者 %programdata%\docker\config\daemon.json(Windows) 来配置 Daemon。
vi /etc/docker/daemon.json
#请在该配置文件中加入(没有该文件的话,请先建一个):
{
"registry-mirrors": ["https://registry.docker-cn.com"],
"live-restore": true
}
或者
{
"registry-mirrors": ["http://hub-mirror.c.163.com"]
"live-restore": true
}
Hello World
一:运行一个helloworld镜像
抓取hello world镜像运行下面的命令,将 image 文件从仓库抓取到本地。
docker image pull是抓取 image 文件的命令
docker pull library/hello-world
library/hello-world是 image 文件在仓库里面的位置,其中library是 image 文件所在的组,hello-world是 image 文件的名字。
使用docker images列出本地已有镜像
$ sudo docker images
使用docker run运行
docker run hello-world
#显示结果
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
二:启动指定镜像的容器,在容器中执行helloworld指令
执行命令 例如:
~$ docker run ubuntu:15.10 /bin/echo "Hello world"
各个参数解析:
- docker: Docker 的二进制执行文件。
- run:与前面的 docker 组合来运行一个容器。
- ubuntu:15.10指定要运行的镜像,Docker首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。
- /bin/echo "Hello world": 在启动的容器里执行的命令
以上命令完整的意思可以解释为:Docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。
docker常用命令
拉取docker镜像
docker pull image_name
查看宿主机上的镜像,Docker镜像保存在/var/lib/docker目录下:
docker images
删除镜像
docker rmi docker.io/tomcat:7.0.77-jre7
或者
docker rmi b39c68b7af30
查看当前有哪些容器正在运行
docker ps
查看所有容器
docker ps -a
启动、停止、重启容器命令:
docker start container_name/container_id
docker stop container_name/container_id
docker restart container_name/container_id
后台启动一个容器后,如果想进入到这个容器,可以使用attach命令:
docker attach container_name/container_id
删除容器的命令:
docker rm container_name/container_id
查看当前系统Docker信息
docker info
从Docker hub上下载某个镜像:
docker pull centos:latest
docker pull centos:latest
执行docker pull centos会将Centos这个仓库的所有镜像下载到本地repository。
Docker 容器使用
Docker 客户端
输入 docker 命令来查看到 Docker 客户端的所有命令选项。
通过命令 docker command --help 更深入的了解指定的 Docker 命令使用方法。例如要查看 docker stats 指令的具体使用方法:
~# docker stats –help
查看 WEB 应用容器
使用 docker ps 来查看正在运行的容器:
~# docker ps
端口信息。
PORTS
0.0.0.0:32769->5000/tcp
表示Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 32769 上。,可以通过32769端口访问该应用
也可以通过 -p 参数来设置不一样的端口,-d是后台运行的意思:
~$ docker run -d -p 5000:5000 training/webapp python app.py
docker 还提供了另一个快捷方式 docker port,使用 docker port 可以查看指定 (ID 或者名字)容器的某个确定端口映射到宿主机的端口号。
查看 WEB 应用程序日志
docker logs [ID或者名字] 可以查看容器内部的标准输出。
例如:~$ docker logs -f bf08b7f2cd89
-f: 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。
查看WEB应用程序容器的进程
使用 docker top 来查看容器内部运行的进程
例如~$ docker top wizardly_chandrasekhar
检查 WEB 应用程序
使用 docker inspect 来查看 Docker 的底层信息。它会返回一个 JSON 文件记录着 Docker 容器的配置和状态信息
例如~$ docker inspect wizardly_chandrasekhar
停止 WEB 应用容器
例如~$ docker stop wizardly_chandrasekhar
重启WEB应用容器
已经停止的容器,可以使用命令 docker start 来启动。
例如~$ docker start wizardly_chandrasekhar
使用docker ps -l 查询最后一次创建的容器
Docker 镜像使用
当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。
列出镜像列表
使用 docker images 来列出本地主机上的镜像
~$ docker images
列表项说明:
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- SIZE:镜像大小
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如ubuntu仓
库源里,有15.10、14.04等多个不同的版本,使用 REPOSITORY:TAG 来定义不同的镜像。
如果要使用版本为15.10的ubuntu系统镜像来运行容器时,命令如下:
~$ docker run -t -i ubuntu:15.10 /bin/bash
如果不指定一个镜像的版本标签,只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像。
查找镜像
可以从 Docker Hub 网站来搜索镜像: https://hub.docker.com/
也可以使用 docker search 命令来搜索镜像。比如通过 docker search 命令搜索 httpd 来寻找适合的httpd镜像作为web服务。
~$ docker search httpd
创建镜像
当从docker镜像仓库中下载的镜像不能满足需求时,可以通过以下两种方式对镜像进行更改。
1.从已经创建的容器中更新镜像,并且提交这个镜像
2.使用 Dockerfile 指令来创建一个新的镜像
更新镜像
更新镜像之前,需要使用镜像来创建一个容器。
在运行的容器内使用 apt-get update 命令进行更新
在完成操作之后,输入 exit命令来退出这个容器。
通过命令 docker commit来提交容器副本。
~$ docker commit -m="has update" -a="xxxx" e218edb10161 xxxx/ubuntu:v2
各个参数说明:
- -m:提交的描述信息
- -a:指定镜像作者
- e218edb10161:容器ID
- runoob/ubuntu:v2:指定要创建的目标镜像名
构建镜像
使用命令 docker build , 从零开始来创建一个新的镜像。为此,我们需要创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像。
~$ cat Dockerfile
FROM centos:6.7
MAINTAINER Fisher "fisher@sudops.com"
RUN /bin/echo 'root:123456' |chpasswd
RUN useradd runoob
RUN /bin/echo 'runoob:123456' |chpasswd
RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE 22
EXPOSE 80
CMD /usr/sbin/sshd –D
每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。
第一条FROM,指定使用哪个镜像源必须指定且需要在Dockerfile其他指令的前面。后续的指令都依赖于该指令指定的image。FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库。
MAINTAINER(用来指定镜像创建者信息)构建指令,用于将image的制作者相关的信息写入到image中。当我们对该image执行docker inspect命令时,输出中有相应的字段记录该信息。
RUN 指令告诉docker 在镜像内执行命令,安装了什么。RUN可以运行任何被基础image支持的命令。如基础image选择了ubuntu,那么软件管理部分只能使用ubuntu的命令。RUN指令可以有多条,每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时,可以用\来换行。
CMD(设置容器启动时执行的操作)设置指令,用于容器启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令。该指令只能在文件中存在一次,如果有多个,则只执行最后一条。
注意:
1) CMD运行在镜像构建之后,容器启动的时候;
2) CMD只执行最后一条
3) CMD可以被用户指定的命令覆盖
ENTRYPOINT(设置容器启动时执行的操作)设置指令,指定容器启动时执行的命令,可以多次设置,但是只有最后一个有效。
该指令的使用分为两种情况,一种是独自使用,另一种和CMD指令配合使用。
当独自使用时,如果你还使用了CMD命令且CMD是一个完整的可执行的命令,那么CMD指令和ENTRYPOINT会互相覆盖只有最后一个CMD或者ENTRYPOINT有效:
CMD echo “Hello, World!”
ENTRYPOINT ls –l
另一种用法和CMD指令配合使用来指定ENTRYPOINT的默认参指令不是一个完整的可执行命令,仅仅是参数部分;ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数:
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]
USER(设置容器的用户)设置指令,设置启动容器的用户,默认是root用户。
EXPOSE(指定容器需要映射到宿主机器的端口)设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口。格式为
EXPOSE <port> [<port> ...]--- EXPOSE 80 443 11211
ENV(用于设置环境变量)构建指令,在image中设置一个环境变量。格式:
ENV JAVA_HOME /path/to/java/dirent
ADD(从src复制文件到容器的dest路径)构建指令,所有拷贝到容器中的文件和文件夹权限为0755,uid和gid为0。格式为:
ADD <src> <dest>
<src> 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url;<dest>是容器中的绝对路径。
COPY复制本地主机的<src>(为Dockerfile所在目录的相对路径,文件或目录)为容器中的<dest>。目标路径不存在时,会自动创建。
当使用本地目录为源目录时,推荐使用COPY。
格式为
COPY <src> <dest>
VOLUME(指定挂载点)设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。格式:
FROM base
VOLUME ["/tmp/data"]
运行通过该Dockerfile生成image的容器,/tmp/data目录中的数据在容器关闭后,里面的数据还存在。例如另一个容器也有持久化数据的需求,且想使用上面容器共享的/tmp/data目录,那么可以运行下面的命令启动一个容器:
docker run -t -i -rm -volumes-from container1 image2 bash
WORKDIR(切换目录)设置指令,可以多次切换(相当于cd命令),对RUN,CMD,ENTRYPOINT生效。格式:
WORKDIR /path/to/workdir
ONBUILD(在子镜像中执行)ONBUILD 指定的命令在构建镜像时并不执行,而是在它的子镜像中执行。
ONBUILD <Dockerfile关键字>
ARG(指定构建过程中使用的环境变量)
然后,使用 Dockerfile 文件,通过 docker build 命令来构建一个镜像。
~$ docker build -t runoob/centos:6.7 .
参数说明:
- -t :指定要创建的目标镜像名
- . :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径
设置镜像标签
使用 docker tag 命令,为镜像添加一个新的标签。
~$ docker tag 860c279d2fec runoob/centos:dev
docker tag 镜像ID,这里是 860c279d2fec ,用户名称、镜像源名(repository name)和新的标签名(tag)。
Docker 容器连接
实现通过端口连接到一个docker容器
案例:
网络端口映射
先创建一个 python 应用的容器。
~$ docker run -d -P training/webapp python app.py
另外,可以指定容器绑定的网络地址,比如绑定 127.0.0.1。
使用 -P 参数创建一个容器,使用 docker ps 来看到端口5000绑定主机端口32768。
我们也可以使用 -p 标识来指定容器端口绑定到主机端口。
另外,我们可以使用 -p指定容器绑定的网络地址,比如绑定127.0.0.1。
这样我们就可以通过访问127.0.0.1:5001来访问容器的5000端口。