赞
踩
docker官方网站,https://www.docker.com
docker文档的官方网站 ,https://docs.docker.com,有时候比较慢,请使用以下内网访问。
docker文档的官方镜像docs/archive:v1.11,大家可以内网访问http://192.168.3.61:4000,由于此网站引用了google网站的相关内容,请大家务必将google的hosts添加到本机,否则页面加载会比较慢。
1979年Unix chroot,实现了系统程序隔离。
2013年,28岁的Solomon在使用python开发dotCloud的PaaS云时发现,使用 LXC技术可以打破产品发布过程中应用开发工程师和系统工程师两者之间无法轻松协作发布产品的难题,2013年3月发布docker 0.1版本,完整提出了一整套打包、分发、运维方案,拉开了基于云计算平台发布产品方式的变革序幕。
平台产品在开发、测试、交付过程中,需要运维人员配置环境,修改表结构,还需要关注依赖软件库的安装。
目前我司平台产品在开发、测试、交付环节中的内容相差很大,开发时大家使用eclipse直接调试;测试时在测试平台上上传软件包供测试人员测试;交付时再由开发人员上传生产平台供用户使用。即上述开发、测试、交付的过程是一致的,有可能会因为环境问题导致生产平台出现问题,但在测试平台上没有发现。
docker的初衷正是如此,即“Build once, Run anywhere; Configureonce, Run anything”。产品的交付就是一个镜像,开发、测试、交付都是这个镜像,确保产品过程中的一致性,减少环境干扰的影响。
基于应用的发布,每个镜像仅是一个应用,多个应用可以共存于同一台机器,一台机器上可以运行成千上万个应用,目前的服务器性能都是过剩的,对于某些低并发应用来讲,一台机器显得过于浪费,使用docker可以很方便的运行多个应用,而且确保这些应用完全隔离,互不影响。
基于Linux的虚拟技术早在1979年就推出了chroot,而在后续时间里又推出了虚拟机产品,比如vmware、virtualbox、xen等。docker与现有的虚拟机技术不相同,如下图说明:
传统的虚拟机技术,是在现有宿主机上再虚拟一层操作系统,它是一个完整操作系统内核。但docker是在宿主机上运行dockerengine这个应用程序,再在其上隔离运行多个应用。
docker,码头工人,logo是一个大鲸鱼背着若干个集装箱。docker的思想与集装箱非常一致,力求建立类似集装箱似的标准块(镜像),通过鲸鱼(docker registry)进行分发、部署使用。docker旨在加快“写代码=》运行代码”的时间,即通过标准化的接口加快产品的“测试、分发、部署、运维”。
每个应用都可以对应一个镜像,举例来说,对于一个标准的基于django的web产品,需要nginx、django、mysql、redis这些应用,如此建立四个镜像(nginx、django、mysql、redis),开发人员的代码打进django镜像,这四个镜像可以部署在同一个机器上,也可以部署在不同机器。用户访问此web产品时,首先由nginx对应的容器捕获,再分发给django容器,django容器调用mysql容器获取数据进行处理。
编译环境的统一
单应用环境的统一部署
多应用间方便的通信
应用方便的迁移
同一台机器,运行多个隔离的应用
不是虚拟机,一个镜像仅仅完成一个业务,一般只有一个进程。
不要将数据和应用共存于一个镜像。
仅支持64bit的操作系统,详细安装步骤请参考官方docs。
必须确保Linux内核版本在3.10以上。
必须按照如下步骤进行,不要直接使用apt-get安装!
(1) 版本号,确保ubuntu版本为12.04、14.04、16.04其中之一,这些ubuntu版本都是LTS版本,即long term support。
(2) apt版本升级,确保可以使用docker源。
命令如下:
$ sudo apt-get update
$ sudo apt-get install apt-transport-httpsca-certificates
$ sudo apt-key adv \
--keyserver hkp://ha.pool.sks-keyservers.net:80 \
--recv-keys 58118E89F3A912897C070ADBF76221572C52609D
(3) 添加docker源
$ echo "<REPO>" | sudo tee/etc/apt/sources.list.d/docker.list
上述的<REPO> 使用下表的数据,根据ubuntu版本。
版本号 | <REPO> |
12.04 (LTS) | deb https://apt.dockerproject.org/repo ubuntu-precise main |
14.04 (LTS) | deb https://apt.dockerproject.org/repo ubuntu-trusty main |
16.04 (LTS) | deb https://apt.dockerproject.org/repo ubuntu-xenial main |
(4) 下载内核支持
$ sudo apt-get update
$ sudo apt-get installlinux-image-extra-$(uname -r) linux-image-extra-virtual
(5) 下载docker
$ sudo apt-get update
$ sudo apt-get install docker-engine
仅支持centos7及以上,必须按照如下步骤进行,不要直接使用yum安装!
(1) yum源更新
$ sudo yum update
$ sudo tee /etc/yum.repos.d/docker.repo<<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF
(2) 下载docker
$ sudo yum install docker-engine
最新的docker原生支持mac,不需要安装虚拟机了。
参考网址:https://docs.docker.com/engine/installation/mac/
最新的docker原生支持windows10 企业版,不需要安装虚拟机了。
参考网址:https://docs.docker.com/engine/installation/windows/
必须在Linux下运行,仅支持64位的x86,直接下载可执行程序。也可以直接从某个已经下载好的机器上直接复制,就可以使用了。
如果是Mac或者windows版本,请参考网址下载。
参考网址:https://docs.docker.com/compose/install/
docker默认使用root用户执行,如果非root执行命令请添加sudo,下同。
(1) 运行docker
ubuntut和centos下,使用service docker restart;重启docker服务也使用这个命令。
centos下如果想开机就运行docker,请使用命令sudo chkconfig docker on
(2) 查看版本
使用命令docker version,目前docker版本已经到了1.12,请使用最新版本。
root@server-ubuntu:~# docker version
Client:
Version: 1.12.3
API version: 1.24
Go version: go1.6.3
Git commit: 6b644ec
Built: Wed Oct 26 21:44:32 2016
OS/Arch: linux/amd64
Server:
Version: 1.12.3
API version: 1.24
Go version: go1.6.3
Git commit: 6b644ec
Built: Wed Oct 26 21:44:32 2016
OS/Arch: linux/amd64
(3) 添加docker源
默认使用docker.io这个国外网站,下载非常慢,建议使用国内中科大的源。
修改文件/etc/default/docker,增加一行如下,再重启docker服务:
DOCKER_OPTS="--registry-mirror=https://docker.mirrors.ustc.edu.cn"
(1) hello-world
执行命令:docker run hello-world,如果看到以下输出则表示成功。
……………..
Hello from Docker!
This message shows that your installationappears to be working correctly.
…………………………
然后再执行命令:docker images,则可以看到hello-world镜像已经下载,此镜像大小为1.848kB
root@wdq-desktop:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest c54a2cc56cbb 5 months ago 1.848kB
(2) ubuntu
执行命令:docker run -it ubuntu /bin/bash
可以看到我们已经进入了一个新的环境,与原有的宿主机完全不相同,其中pid为1的进程居然是/bin/bash。
这个环境是一个mini版本的ubuntu,在其中可以做很多事情。同时这个镜像是后续所有镜像的基石,即其他镜像都是以ubuntu镜像为基础的。
docker是一个C/S架构的产品,分为两个部分:docker engine和docker hub。
docker engine,安装在使用者的主机上,C/S架构,Client即手动运行各个docker命令,Server即是docker daemon,利用主机上的镜像Images运行进入容器环境Containers。
docker hub,用于分发镜像的Saas平台,官网是docker.io,用户可以自行创建私有的平台,供内部人员使用。
类似于iso镜像文件,是静态存储的文件集合,镜像是只读系统。比如在前面章节下载的ubuntu,就是一个典型的镜像。可以直接使用client从docker官网下载已有的镜像,或者自已build一个镜像,详细参见《docker之镜像管理》。
镜像文件一般存储于/var/lib/docker/目录下,也可以在/etc/default/docker配置文件中指定位置。其中的文件内容非常难以理解,一般通过docker client进行操作。
镜像文件的描述格式为“[url:port/][group/]name[:/TAG]”,可以看到除name外,其他均是可选项,以上述的ubuntu为例,在使用docker pull下载时,name为ubuntu,TAG为空则默认为latest(所以使用docker images可以看到TAG),url和port也为空则表示从官网下载,由于我们已经配置了中科大的源为镜像源则会首先从中科大的源下载,group也为空。
镜像文件是分层结构,使用命令docker history查看:
ubuntu镜像由6层组成,最底层为一个128.2MB大小的文件,其上五层都是一堆shell命令,这6层系统通过Linux的aufs文件系统合并之后,呈现给用户的是一个完整的文件系统。
因为镜像的分层原因,会节省主机的存储开销。举例来说,如果已经下载了ubuntu镜像,再下载基于此ubuntu镜像的其他镜像,则此最基本的ubuntu镜像不需要再下载了,只需要下载ubuntu镜像之上的内容。这个也很类似代码管理系统中的diff。
容器是镜像的运行环境,镜像只有在容器中才有意义,容器必须依赖一个镜像,如下图:
从上图可以看出,容器在运行时在镜像层之外又单独加了可读写的一层,所有对容器的修改动作均在这一层中处理,镜像内容不会作任何改变。
使用docker run命令启动一个容器,容器创建后只要其主进程退出(pid==1)则容器退出,默认情况下退出的容器仍然存在,可以继续使用命令dockerstart运行,如果不需要可以使用docker rm 删除容器。
上图是运行docker run的示意图,docker run相当于执行了两重命令,一个是创建一个容器,使用docker create,从镜像创建容器;另一个是docker start,运行一个容器。
docker registry,存储镜像的仓库,docker官方的仓库是docker.io,有两个部分,一个是仅有仓库,容许所有人下载、上传、搜索,另一个是私有仓库,仅允许特定人员操作。
公司内部使用的话一般建议搭建私有仓库,搭建docker 仓库用的也是一个镜像,此镜像的名称是registry,版本是2。目前有价值的业务均以docker镜像的方式提供,registr如是,文档docs也如是。
本章节搭建基于django的任务管理系统,需要用到mysql、redis、task三个镜像,其中mysql/redis为两个公共的镜像,其Dockerfile都是从官网的github下载来的,task镜像是基于django的工程,任务管理系统的代码镜像。这三个镜像目前已经构建好,只需要从私有仓库下载即可。
目前公司内部搭建了一个docker私有仓库,域名是dockerreg.maxnetsys.com,对应的IP目前必须是192.168.3.61。
l 修改/etc/hosts
确保域名dockerreg.maxnetsys.com指向的是192.168.3.61。如下图:
l 使用HTTPS证书
将文件ca.crt放置到如下目录位置,再重启docker服务。
docker pull dockerreg.maxnetsys.com:5000/maxnet-mysql
docker pull dockerreg.maxnetsys.com:5000/maxnet-django
docker pull dockerreg.maxnetsys.com:5000/maxnet-redis
使用如下三个命令下载镜像。
使用docker-compose工具同时操作多个容器。在当前目录下生成docker-compose.yml文件,此文件为yml格式(类似xml),请务必使用对应的编辑器进行编辑,内容如下:
version: "2"
services:
db:
image: dockerreg.maxnetsys.com:5000/maxnet-mysql:latest
expose:
-"3306"
volumes:
-mysql_data:/var/lib/mysql
-mysql_log:/var/log/mysql
environment:
MYSQL_ROOT_PASSWORD: '123456'
MYSQL_USER: 'xdpi'
MYSQL_PASSWORD: 'maxnet@5668'
redis_main: # slave redis must using anothercontainer with the same image
image: dockerreg.maxnetsys.com:5000/maxnet-redis:latest
volumes:
-redis_data:/var/lib/redis
-redis_log:/var/log/redis
expose:
-"6379"
task:
image: dockerreg.maxnetsys.com:5000/maxnet-task:latest
command: python3 manage.py runserver 0.0.0.0:8000
# volumes:
# -../image:/code
links:
-db
-redis_main
ports:
-"8000:8000"
volumes:
mysql_data:
mysql_log:
redis_data:
redis_log:
在当前目录下执行docker-compose up,如此会以前台方式进行,当前窗口被挂住。可以使用-d参数让其后台运行,如此当前窗口可以继续使用。
在浏览器在输入http://IP:8000/report,如此就进入了任务管理系统。
需要停止业务时,请使用docker-compose down,还可以使用start/stop停止其中的某个容器,详细请参考docker-compose相关文档。
mysql容器监听在3306端口,其服务名称为db,故在report镜像的代码中,对应django工程的settings.py文件中的database 配置,其中mysql的主机名请使用db;mysql的数据区写到了数据卷“mysql_data”,日志区也写到了数据卷“mysql_log”,这些数据卷不属于某容器,即使容器被删除,这些数据卷内容仍然存在。
task容器为主业务,监听端口8000且映射到宿主机8000端口,如此其他机器可以访问此机器的8000端口来使用此业务。task容器需要使用数据库db和缓存redis,故在links指定。redis也使用了数据卷来存储日志和数据。
本章节记录经常遇到的问题。
(1) 如何进入一个正在运行的容器?
docker exec -it your_container_name /bin/bash
千万不要在容器中运行sshd再登录了。
(2) 如何执行容器中的命令?
docker exec -it your_container_name your_cmd_with_args
注意your_cmd_with_args,其中可以有分号,比如可以查看容器中的某个文件
(3) 如何导出容器中的数据卷内容?
docker run -v .:/cpdir --from-volume volume_name your_image_name cp volumedir /cpdir
基本思想是将当前目录挂载到容器中的某个固定目录比如/cpdir,然后同时挂载数据卷再将数据卷的内容复制出来。
(4) docker-compose.yml所在目录名称修改后原有容器无法删除?
docker-compose创建容器和数据卷时,都加了一个前缀,此前缀恰好是目录名称,故修改所在目录名称后,导致docker-compose原有的容器无法管理了,也无法停止掉,此时必须使用docker-compose down --remove-orphans
关于数据卷内容请参考《docker之数据存储》;
docker-compose内容请参考《docker之compose》;
镜像相关内容请参考《docker之镜像制作》;
仓库相关内容请参考《docker之仓库管理》;Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。