参考网站:
Docker官网文档 https://docs.docker.com
中文翻译 http://www.widuu.com/docker/
Docker Hub https://hub.docker.com/
Docker博客 https://blog.docker.com/
阿里云Docker镜像库 https://dev.aliyun.com
一、Docker简介
1.什么是docker? Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。 官方的描述是:Build, Ship, and Run Any App, Anywhere 在任何地方部署,传输,运行任何应用 Docker类似虚拟机的概念,但是跟虚拟机比起来更灵活,速度更快,CPU/内存消耗更低,关键是更方便管理。与虚拟化技术的不同点在于下面几点: 1)虚拟化技术依赖物理CPU和内存,是硬件级别的;而docker构建在操作系统上,利用操作系统的containerization技术,所以docker甚至可以在虚拟机上运行。 2)虚拟化系统一般都是指操作系统镜像,比较复杂,称为“系统”;而docker开源而且轻量,称为“容器”,单个容器适合部署少量应用,比如部署一个redis、一个memcached 3)传统的虚拟化技术使用快照来保存状态;而docker在保存状态上不仅更为轻便和低成本,而且引入了类似源代码管理机制,将容器的快照历史版本一一记录,切换成本很低 4)传统的虚拟化技术在构建系统的时候较为复杂,需要大量的人力;而docker可以通过Dockfile来构建整个容器,重启和构建速度很快。更重要的是Dockfile可以手动编写,这样应用程序开发人员可以通过发布Dockfile来指导系统环境和依赖,这样对于持续交付十分有利 5)Dockerfile可以基于已经构建好的容器镜像,创建新容器。Dockerfile可以通过社区分享和下载,有利于该技术的推广
2.结构组成 底层由"核心系统kernel,文件系统等构成",上面是镜像(p_w_picpath),分为基础镜像(只读)和普通镜像,所有镜像可以直接启动生成一个实例(container),container就可以理解为一个可以直接运行的虚拟机了。 container和p_w_picpath在Docker的世界里,Image是指一个只读的层(Layer),这里的层是AUFS里的概念,最直观的方式就是看一下docker官方给出的图 Docker使用了一种叫AUFS的文件系统,这种文件系统可以让你一层一层地叠加修改你的文件,最底下的文件系统是只读的,如果需要修改文件,AUFS会增加一个可写的层(Layer),这样有很多好处,例如不同的Container可以共享底层的只读文件系统(同一个Kernel),使得你可以跑N多个Container而不至于你的硬盘被挤爆了!这个只读的层就是Image!而如你所看到的,一个可写的层就是Container。 那Image和Container的区别是什么?很简单,他们的区别仅仅是一个是只读的层,一个是可写的层,你可以使用docker commit 命令,将你的Container变成一个Image,也就是提交你所运行的Container的修改内容,变成一个新的只读的Image,这非常类似于git commit命令。 Docker 由下面这些组成: 1) Docker 服务器守护程序(server daemon),用于管理所有的容器。 2) Docker 命令行客户端,用于控制服务器守护程序。 3) Docker 镜像:查找和浏览 docker 容器镜像。
3.Docker特性 文件系统隔离:每个进程容器运行在完全独立的根文件系统里。 资源隔离:可以使用cgroup为每个进程容器分配不同的系统资源,例如CPU和内存。 网络隔离:每个进程容器运行在自己的网络命名空间里,拥有自己的虚拟接口和IP地址。 写时复制:采用写时复制方式创建根文件系统,这让部署变得极其快捷,并且节省内存和硬盘空间。 日志记录:Docker将会收集和记录每个进程容器的标准流(stdout/stderr/stdin),用于实时检索或批量检索。 变更管理:容器文件系统的变更可以提交到新的映像中,并可重复使用以创建更多的容器。无需使用模板或手动配置。 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上,例如运行一个一次性交互shell。
二、Docker的安装使用
1.安装环境
Docker 可以安装在 Linux,Mac,Windows上,可以参考官方安装文档 https://docs.docker.com/engine/installation/linux/centos/。
环境要求必须是Centos6.5以上,X64位系统,内核版本至少3.10
默认目录文件结构说明
/etc/sysconfig/docker 默认配置文件 /var/lib/docker/ Docker相关的本地资源 /var/lib/docker/container/ 存放容器信息 /var/lib/docker/graph/ 存放镜像信息
2.两种安装方法,yum直接安装和从 get.docker.com 调用脚本安装
2.1 使用yum 安装 # yum install docker # docker --version # 检查是否安装成功 2.2 使用官方提供的脚本安装(首先确定你已经在"墙外") # curl -sSL https://get.docker.com/ | sh 17.04版本以后的安装方法 # export CHANNEL=stable # curl -fsSL https://get.docker.com/ | sh -s -- --mirror Aliyun 启动 # service docker start # chkconfig docker on # 开机启动 下载最新的centos镜像 # docker pull centos # docker p_w_picpaths # 查看所有镜像 测试镜像 # docker run -i -t centos /bin/bash # exit # 退出 注意:若有提示"Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning." 修改文件 “/etc/sysconfig/docker-storage”, 按照提示添加内容 “DOCKER_STORAGE_OPTIONS="--storage-opt dm.no_warn_on_loop_devices=true"” 然后重启docker # service docker restart
3.常用命令
常用命令可分为以下几种 1.容器生命周期管理 # docker [run|start|stop|restart|kill|rm|pause|unpause] 2.容器操作运维 # docker [ps|inspect|top|attach|events|logs|wait|export|port] 3.容器rootfs命令 # docker [commit|cp|diff] 4.镜像仓库 # docker [login|pull|push|search] 5.本地镜像管理 # docker [p_w_picpaths|rmi|tag|build|history|save|import] 6.其它命令 # docker [info|version]
3.1)镜像相关操作命令: 创建镜像的方法有三种 基于已有镜像的容器创建 基于本地模板导入 基于Dockerfile文件创建 commit 基于已有镜像的容器再生成一个新的镜像 # docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] -m,--message="" 提交信息,为镜像描述内容 -a,--author="" 作者信息 -p,--pause=true 提交时暂停容器运行 My_Container:1 是提交的镜像名称和版本 # docker commit -m "Centos7 x64 First Image" -a "Loren" 33d619155d03 My_centos7:1 import 基于本地模板导入容器快照,将一个容器快照文件导入本地 # cat centos.tar | docker import - test/centos:v1.0 build 根据Dockerfile文件创建一个新的镜像 # docker build [OPTIONS] PATH | URL | - -t 设定镜像名称及其标示号 -f,--file=Dockerfile 指定Dockerfile文件路径 # docker build -t test:2 -f /opt/ search Image_name 在docker index中搜索p_w_picpath --automated=false -s N, --stars=0 指定评价为N星级以上的镜像 # docker search centos6 pull Image_name 从docker register server 中下拉p_w_picpath或者repository # docker pull centos # docker pull centos:centos6 # docker pull dl.dockerpool.com:5050/centos:6.8 指定网站下载 push 推送一个p_w_picpath或者repository到registry 上传之前要把上传的p_w_picpath的tag修改为 hup用户名/镜像名字:tag 如 # docker tag centos6.8:v1 644597521/centos6.8:v1 p_w_picpaths 显示本地的所有镜像列表 rmi 删除指定id的镜像 tag 修改镜像名 # docker tag test:1 My_p_w_picpath:v2 修改test标记好为1的名称为My_p_w_picpath标记号为v2 save 保存镜像到本地文件 Usage: docker save [OPTIONS] IMAGE [IMAGE...] -o, --output="" # docker save -o centos_6.4.tar centos6.4:v1 # 导出本地的centos6.4:v1镜像为centos_6.4.tar文件 load 将本地文件导入到本地镜像库 Usage:docker load [OPTIONS] -i, --input="" # docker load < centos_6.4.tar # 将centos_6.4.tar文件导入到本地镜像列表 inspect 显示镜像或容器的信息。返回的是JSON格式信息,若只要其中一项内容,可以使用-f指定
3.2)容器常用操作命令 run 运行一个新的container # Usage:docker run [OPTIONS] IMAGE [COMMAND] [ARG...] -a,--attack -i,--interactive=false 以交互模式运行容器,通常和-t搭配 -t,--tty=false 分配一个伪输入终端 -d 后台运行 -P 允许外部访问容器所有开启的端口 -p 端口映射 -p 80:80 --name 指定启动后容器的名字 # docker run -i -t centos # docker run -i -t -d centos /bin/bash # docker run -i -t -d --name My_Container centos /bin/bash # docker run -i -t -d -p 80:80 --name My_Container centos /bin/bash -v,--volume=[] 创建数据卷 /mnt 在容器中创建一个数据卷 /webapp:/src/webapp 目录挂载。将本地的webapp目录挂载到容器的/src/webapp。容器和宿主机的挂载目录都会同时变化 /test.txt:/tmp/text.txt 文件挂载。将本地的/test.txt文件挂载到容器的/tmp/text.txt(注意,只能修改容器挂载内的文件,否则不同步) # docker run -ti -v /da --name=dbdata centos 创建一个容器dbdata,并创建一个数据卷挂载容器dbdata的/da目录 --volume-from 共享挂载数据卷 # # docker run -ti -v /mnt --name db centos 创建一个数据卷容器db,并创建一个数据卷挂载到容器db的/mnt目录下 # docker run -ti --volume-from=db --name db1 centos # db1容器挂载db 容器中的数据卷 # docker run -ti --volume-from=db --name db2 centos # db2容器挂载db 容器中的数据卷 此时三个容器db,db1,db2都可以分享目录/mnt --link 连接其他容器 --link NAME:Alias Name要建立连接的容器名,Alias连接的容器的别名 # docker run -ti -d -P --name web --link lamp:lamp centos6.4 /bin/bash 新建容器web和已经运行的容器lamp连接 ps 显示容器的列表 -a 显示所有信息 -q 只显示ID # docker inspect 5d20c5528521 显示容器的详细信息 # docker ps -a -q ID # docker inspect -f "{{ .State.Pid }}" 5d20c5528521 显示运行容器的PID stop|start|restart 停止|启动|重启容器 exec 进入容器(推荐使用) # docker exec [OPTIONS] CONTAINER COMMAND [ARG...] # docker exec -t -i 216c623071b3 /bin/bash attack CONTAINER_ID 进入容器 # docker attack 216c623071b3 使用 attach 命令有时候并不方便。当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了 nsenter # yum install util-linux # PID=$(docker inspect -f "{{ .State.Pid }}" 5d20c5528521) # nsenter --target $PID --mount --uts --ipc --net --pid # nsenter --target 10981 --mount --uts --ipc --net --pid -t, --target <pid> 要获取名字空间的目标进程 -m, --mount[=<file>] enter mount namespace -u, --uts[=<file>] enter UTS namespace (hostname etc) -i, --ipc[=<file>] enter System V IPC namespace -n, --net[=<file>] enter network namespace -p, --pid[=<file>] enter pid namespace rm 删除一个容器 -f, --force=true 强制删除 -l, --link=false 删除容器的连接,但保留容器 -v, --volumes=false 删除容器挂载的数据卷 export 导出容器,导出一个已经创建的容器到一个文件,不管此时这个容器是否处于运行状态 -o, --output="" # docker export 929bf12bc6ea > centos_6.4_php.tar
3.3)其它常用命令 docker -H 127.0.0.1:1234 -d & 修改服务端监听本地的TCP连接1234端口 volume 管理docker的文件 login 登录仓库https://hub.docker.com/,登录成功后信息保存文件在用户家目录/.docker/config.json 输入用户,密码,邮件。 下载 .bashrc_docker,并将内容放到 .bashrc 中 # wget -P ~ https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker; # echo "[ -f ~/.bashrc_docker ] && . ~/.bashrc_docker" >> ~/.bashrc # source ~/.bashrc 这个文件中定义了很多方便使用 Docker 的命令,例如 docker-pid 可以获取某个容器的 PID; 而 docker-enter 可以进入容器或直接在容器内执行命令
三、Dockerfile的使用
Dockerfile 一般分为四部分: 基础镜像信息、维护者信息、镜像操作指令、容器启动执行指令 例子: # cat Dockerfile # Dockerfile 注释 FROM centos6.8:1 指定基于的基础镜像,第一条必须为FROM指令 MAINTAINER loren 维护者信息 LABEL Date='2016-06-06 10:11' RUN yum install -y ntpdate;yum install -y vim 镜像的操作指令 CMD 容器启动时执行的指令
指令: 1.FROM <p_w_picpath>:<tag> 告诉Docker使用哪个镜像作为基础,第一条必须为FROM指令,可以使用多个FROM指令(每个镜像一次) 2.MAINTAINER <author name> 作者信息 3.RUN <Command>或 RUN ["executable","param1","param2"] 前者在shell终端运行命令,即 /bin/sh -c;后者使用exec执行,如 RUN ["/bin/bash", "-c", "echo hello"] 4.CMD 描述容器启动后运行的服务命令,有三种格式 CMD ["executable", "param1", "param2"] 使用exec执行(推荐使用) CMD ["/bin/bash","-c","echo hello"] CMD command param1 param2 在/bin/sh 中执行,以“/bin/sh -c”方法执行。提供给需要交互的应用 CMD echo "hello world" CMD ["param1", "param2"] 提供给ENTRYPOINT 的默认参数 CMD ["-D","--help"] 指定启动容器时执行的命令,每个Dockerfile 只能有一条 CMD 命令。如果多个则只会执行最后一条 若果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令 5.EXPOSE 向外部开放端口 EXPOSE <port> [<port>...] EXPOSE 22 80 8443 6.ENV 指定一个环境变量,会被后续RUN指令使用,并在容器运行时保持 EVN <key> <value> ENG PG_MAJOR 9.3.4 RUN ..... ENV PATH /usr/local/postgres-$PG-MAJOR/bin/:$PATH 7.ADD 将复制指定的<src> 到容器的 <dest>,其中<src>可以是Dockerfile所在目录的一个相对路径(文件或目录),也可以是一个URL,还可以是一个tar文件(会自动解压为目录) ADD <src> <dest> 8.COPY 复制本地的主机的 <src> 为容器中的 <dest>。若目标路径不存在时,会自动创建 COPY <src> <dest> 9.ENTRYPOINT 容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。 每个Dockerfile中只能有一个 ENTRYPOINT,当指定多个 ENTRYPOINT时,只有最后一个生效 ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2 (shell中执行) 一般是配合CMD使用,CMD提供默认参数,如: ENTRYPOINT ["/usr/sbin/sshd"] CMD ["-D"] 10.VOLUME 创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等 VOLUME ["/data"] 11.USER 指定容器运行时的用户名或UID,后续的 RUN也会使用指定用户。使用gosu代替sudo获取管理员权限 USER daemon 12.WORKDIR 指定配置工作目录 WORKDIR /path/to/workdir WORKDIR /a WORKDIR b 13.ONBUILD 配置当所创建的镜像作为其他新创建镜像的基础镜像时,所执行的操作指令 ONBUILD [INSTRUCTION] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src
Dockerfile 实例
下面是创建sshd服务的Dockerfile文件实例
# cat /opt/docker_builder/sshd/Dockerfile FROM centos6.8:1 # 指定基础镜像 MAINTAINER Loren <[email protected]> LABEL Date='2016-06-14 16:39' # Install sshd service 安装sshd服务 RUN yum install -y openssh-server # Add authorized_keys -> /root/.ssh/authorized_keys 和本机建立互信 RUN mkdir -p /root/.ssh;chmod 700 /root/.ssh ADD authorized_keys /root/.ssh/authorized_keys # Password for ROOT 设置容器的root密码 RUN echo '1' | passwd root --stdin # script for sshd 提供开机自启动脚本 ADD ssh.sh /root/ssh.sh RUN chmod 755 /root/ssh.sh # Read from socket failed: Connection reset by peer 当ssh连接容器时的错误提示解决方法 RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key;ssh-keygen -t dsa -f /etc/ssh/ssh_host_rsa_key # OPEN Port 22 开发ssh服务容器的端口 EXPOSE 22 # Command 开机启动脚本 CMD ["/root/ssh.sh"] # cat ssh.sh #!/bin/bash /usr/sbin/sshd -D 通过Dockerfile 文件创建镜像,并指定Dockerfile文件路径 # docker build -t sshd:t1 /opt/docker_builder/sshd/ # docker run -d -p 2020:22 sshd:t1 启动sshd服务容器,本机端口2020映射到容器22端口 此时就可以通过本机的ssh连接到sshd服务容器 # ssh IP 2020
ssh连接失败提示: "Read from socket failed: Connection reset by peer" 解决方法: #ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key;ssh-keygen -t dsa -f /etc/ssh/ssh_host_rsa_key
使用Dockerfile 安装nginx实例
# cat Dockerfile FROM sshd/centos6.8:t1 MAINTAINER Loren <[email protected]> [2016-06-15 14:48] # Install nginx RUN yum install -y nginx RUN echo "daemon off;" >> /etc/nginx/nginx.conf RUN echo "Hello Container Nginx!" >> /usr/share/nginx/html/index.html EXPOSE 80 CMD ["/usr/sbin/nginx"] # docker build -t nginx/centos6.8:t1 . 创建nginx容器 # docker run -d -p 8000:80 nginx/centos6.8:t1 启动nginx容器
使用Dockerfile安装Tomcat实例
目录结构: /opt/tomcat/ ├── Dockerfile └── packages ├── apache-tomcat-6.0.41.zip └── jdk-6u45-linux-x64-rpm.bin # cat Dockerfile FROM sshd:centos6.8 MAINTAINER Loren <[email protected]> [2016-06-17 16:13] ENV JAVA_HOME /usr/java/jdk1.6.0_45 ENV JRE_HOME $JAVA_HOME/jre ENV PATH $PATH:$JAVA_HOME/bin # Base programesoft RUN yum install -y unzip vim wget # For jdk RUN mkdir -p /soft ADD ./packages/jdk-6u45-linux-x64-rpm.bin /soft RUN cd /soft;chmod 755 jdk-6u45-linux-x64-rpm.bin;./jdk-6u45-linux-x64-rpm.bin # For tomcat RUN mkdir -p /data COPY ./packages/apache-tomcat-6.0.41.zip /soft RUN unzip -o /soft/apache-tomcat-6.0.41.zip -d /data/ RUN chmod 777 /data/apache-tomcat-6.0.41/bin/*.sh EXPOSE 8080 CMD ["/data/apache-tomcat-6.0.41/bin/catalina.sh", "run"] # docker build -t tomcat/centos6.8:v1 /opt/tomcat/ 创建tomcat/centos6.8:v1容器 # docker run -d -P tomcat/centos6.8:v1 启动tomcat/centos6.8:v1 容器
使用Dockerfile安装Tomcat实例
目录结构: /opt/httpd/ ├── Dockerfile ├── run_httpd.sh └── sample └── index.html # cat Dockerfile # For apache install FROM centos6.8:1 MAINTAINER Loren <[email protected]> [2016-06-15 11:08] # Installed RUN yum install -y httpd RUN sed -i 's/#\(ServerName\)\ www.example.com:80/\1\ localhost:80/g' /etc/httpd/conf/httpd.conf # Add html COPY sample/index.html /var/www/html # Simple startup scipt to avoid some issues observed with container restart ADD run_httpd.sh /run_httpd.sh RUN chmod 755 /run_httpd.sh # OPEN port 80 EXPOSE 80 CMD ["/run_httpd.sh"] ENV HOME /root WORKDIR /root # cat run_httpd.sh #!/bin/bash # FileName: run_httpd.sh # Author: Loren # Date: 2016-06-15 11:22 # Info: For start httpd with container restart #exec /usr/sbin/apachectl -D FOREGROUND /usr/sbin/httpd -k start # cat sample/index.html <!DOCTYPE html> <html> <body> <h1>Hello, Container!</h1> </body> </html> # docker build -t httpd/centos6.8:v1 /opt/httpd/ 创建httpd容器 # docker run -d -P httpd/centos6.8:v1 启动httpd容器