CentOSLinux安装Docker容器

Docker 使用

环境说明

  • CentOS 7.3(不许确地说:要求必须是 CentOS 7 64位)
  • 不建议在 Windows 上使用

Docker 基本概念

  • 官网:https://www.docker.com/
  • 宿主机:安装 Docker 的那台电脑
  • Docker:一个虚拟化软件,你能够认为是相似:VMware、Virtualbox
  • 镜像:能够认为是相似 Windows 下的:XXXX.iso
  • 容器:容器为镜像的实例,能够认为是 Virtualbox 运行 XXXX.iso 后的效果
  • 官网的镜像仓库地址:https://store.docker.com/
  • 对开发来说总结一个最简单的说法:在 Maven 未产生的年代,jar 包要随着开发项目走到哪里跟到哪里。有了 Maven 写好 pom.xml 便可。此时的 Docker 就比如如 Maven,帮你省去了开发过程当中的部署环境差别,你不再能随便说:你的系统能够运行,个人系统就不行。如今别人连系统都帮你作好了。
  • 玩法理念:单进程,一个容器最好最专一去作一个事情。虽然它能够既装 MySQL,又装 Nginx 等等,可是让一个容器只作好一件事是最合适的。
  • 其余通俗解释:

Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,能够把货物规整的摆放起来。而且各类各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么我就不须要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就能够用一艘大船把他们都运走。 docker就是相似的理念。如今都流行云计算了,云计算就比如大货轮。docker就是集装箱。 1.不一样的应用程序可能会有不一样的应用环境,好比.net开发的网站和php开发的网站依赖的软件就不同,若是把他们依赖的软件都安装在一个服务器上就要调试好久,并且很麻烦,还会形成一些冲突。好比IIS和Apache访问端口冲突。这个时候你就要隔离.net开发的网站和php开发的网站。常规来说,咱们能够在服务器上建立不一样的虚拟机在不一样的虚拟机上放置不一样的应用,可是虚拟机开销比较高。docker能够实现虚拟机隔离应用环境的功能,而且开销比虚拟机小,小就意味着省钱了。 2.你开发软件的时候用的是Ubuntu,可是运维管理的都是centos,运维在把你的软件从开发环境转移到生产环境的时候就会遇到一些Ubuntu转centos的问题,好比:有个特殊版本的数据库,只有Ubuntu支持,centos不支持,在转移的过程中运维就得想办法解决这样的问题。这时候要是有docker你就能够把开发环境直接封装转移给运维,运维直接部署你给他的docker就能够了。并且部署速度快。 3.在服务器负载方面,若是你单独开一个虚拟机,那么虚拟机会占用空闲内存的,docker部署的话,这些内存就会利用起来。 总之docker就是集装箱原理。php

  • Docker 的优势:
  • 持续部署与测试

Docker在开发与运维的世界中具备极大的吸引力,由于它能保持跨环境的一致性。在开发与发布的生命周期中,不一样的环境具备细微的不一样,这些差别多是因为不一样安装包的版本和依赖关系引发的。然而,Docker能够经过确保从开发到产品发布整个过程环境的一致性来解决这个问题。 Docker容器经过相关配置,保持容器内部全部的配置和依赖关系始终不变。最终,你能够在开发到产品发布的整个过程当中使用相同的容器来确保没有任何差别或者人工干预。 使用Docker,你还能够确保开发者不须要配置彻底相同的产品环境,他们能够在他们本身的系统上经过VirtualBox创建虚拟机来运行Docker容器。Docker的魅力在于它一样可让你在亚马逊EC2实例上运行相同的容器。若是你须要在一个产品发布周期中完成一次升级,你能够很容易地将须要变动的东西放到Docker容器中,测试它们,而且使你已经存在的容器执行相同的变动。这种灵活性就是使用Docker的一个主要好处。和标准部署与集成过程同样,Docker可让你构建、测试和发布镜像,这个镜像能够跨多个服务器进行部署。哪怕安装一个新的安全补丁,整个过程也是同样的。你能够安装补丁,而后测试它,而且将这个补丁发布到产品中。html

  • 环境标准化和版本控制

Docker容器能够在不一样的开发与产品发布生命周期中确保一致性,进而标准化你的环境。除此以外,Docker容器还能够像git仓库同样,可让你提交变动到Docker镜像中并经过不一样的版原本管理它们。设想若是你由于完成了一个组件的升级而致使你整个环境都损坏了,Docker可让你轻松地回滚到这个镜像的前一个版本。这整个过程能够在几分钟内完成,若是和虚拟机的备份或者镜像建立流程对比,那Docker算至关快的,它可让你快速地进行复制和实现冗余。此外,启动Docker就和运行一个进程同样快。java

  • 隔离性

Docker能够确保你的应用程序与资源是分隔开的。几个月前,Gartner发表了一篇报告,这份报告说明了运行Docker 容器进行资源隔离的效果和虚拟机(VM)管理程序同样的好,可是管理与控制方面还须要进行完善。咱们考虑这样一个场景,你在你的虚拟机中运行了不少应用程序,这些应用程序包括团队协做软件(例如Confluence)、问题追踪软件(例如JIRA)、集中身份管理系统(例如Crowd)等等。因为这些软件运行在不一样的端口上,因此你必须使用Apache或者Nginx来作反向代理。到目前为止,一切都很正常,可是随着你的环境向前推动,你须要在你现有的环境中配置一个内容管理系统(例如Alfresco)。这时候有个问题发生了,这个软件须要一个不一样版本的Apache Tomcat,为了知足这个需求,你只能将你现有的软件迁移到另外一个版本的Tomcat上,或者找到适合你现有Tomcat的内容管理系统(Alfresco)版本。对于上述场景,使用Docker就不用作这些事情了。Docker可以确保每一个容器都拥有本身的资源,而且和其余容器是隔离的。你能够用不一样的容器来运行使用不一样堆栈的应用程序。除此以外,若是你想在服务器上直接删除一些应用程序是比较困难的,由于这样可能引起依赖关系冲突。而Docker能够帮你确保应用程序被彻底清除,由于不一样的应用程序运行在不一样的容器上,若是你不在须要一款应用程序,那你能够简单地经过删除容器来删除这个应用程序,而且在你的宿主机操做系统上不会留下任何的临时文件或者配置文件。除了上述好处,Docker还能确保每一个应用程序只使用分配给它的资源(包括CPU、内存和磁盘空间)。一个特殊的软件将不会使用你所有的可用资源,要否则这将致使性能下降,甚至让其余应用程序彻底中止工做。node

  • 安全性

如上所述,Gartner也认可Docker正在快速地发展。从安全角度来看,Docker确保运行在容器中的应用程序和其余容器中的应用程序是彻底分隔与隔离的,在通讯流量和管理上赋予你彻底的控制权。Docker容器不能窥视运行在其余容器中的进程。从体系结构角度来看,每一个容器只使用着本身的资源(从进程到网络堆栈)。做为紧固安全的一种手段,Docker将宿主机操做系统上的敏感挂载点(例如/proc和/sys)做为只读挂载点,而且使用一种写时复制系统来确保容器不能读取其余容器的数据。Docker也限制了宿主机操做系统上的一些系统调用,而且和SELinux与AppArmor一块儿运行的很好。此外,在Docker Hub上可使用的Docker镜像都经过数字签名来确保其可靠性。因为Docker容器是隔离的,而且资源是受限制的,因此即便你其中一个应用程序被黑,也不会影响运行在其它Docker容器上的应用程序。linux

  • 多云平台

Docker最大的好处之一就是可移植性。在过去的几年里,全部主流的云计算提供商,包括亚马逊AWS和谷歌的GCP,都将Docker融入到他们的平台并增长了各自的支持。Docker容器能运行在亚马逊的EC2实例、谷歌的GCP实例、Rackspace服务器或者VirtualBox这些提供主机操做系统的平台上。举例来讲,若是运行在亚马逊EC2实例上的Docker容器可以很容易地移植到其余几个平台上,好比说VirtualBox,而且达到相似的一致性和功能性,那这将容许你从基础设施层中抽象出来。除了AWS和GCP,Docker在其余不一样的IaaS提供商也运行的很是好,例如微软的Azure、OpenStack和能够被具备不一样配置的管理者所使用的Chef、Puppet、Ansible等。git

Docker 安装和基本配置

  • 主要有两个版本:

Docker Enterprise Edition (Docker EE) is designed for enterprise development and IT teams who build, ship, and run business critical applications in production at scale. Docker EE is integrated, certified, and supported to provide enterprises with the most secure container platform in the industry to modernize all applications. For more information about Docker EE, including purchasing options, see Docker Enterprise Edition. Docker Community Edition (Docker CE) is ideal for developers and small teams looking to get started with Docker and experimenting with container-based apps. Docker CE is available on many platforms, from desktop to cloud to server. Docker CE is available for macOS and Windows and provides a native experience to help you focus on learning Docker. You can build and share containers and automate the development pipeline all from a single environment. Docker CE has both stable and edge channels. Stable builds are released once per quarter and are supported for 4 months. Edge builds are released once per month, and are supported for that month only. If you subscribe to the Edge channel on Linux distributions, you should also subscribe to the Stable channel.github

  • 官网总的安装手册:https://docs.docker.com/install/web

  • 官网 CentOS 安装手册:https://docs.docker.com/install/linux/docker-ce/centos/正则表达式

  • 目前也支持 Windows,特别是 Windows 10,直接官网一个安装包便可搞定。redis

  • Windows 10 的 Docker 安装说明:https://store.docker.com/editions/community/docker-ce-desktop-windows

  • 我这里选择 Docker CE 版本:

  • CentOS 安装过程:

    • sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    • 添加 repo(可能网络会很慢,有时候会报:Timeout,因此要多试几回)
    • sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    • sudo yum makecache fast
    • sudo yum install -y docker-ce,大小:19M,速度很慢。
  • 查看配置文件位置:systemctl show --property=FragmentPath docker

  • 启动 Docker:systemctl start docker.service

  • 中止 Docker:systemctl stop docker.service

  • 查看状态:systemctl status docker.service

  • 运行 hello world 镜像:sudo docker run hello-world

    • 由于是第一次使用,因此没这个镜像,须要一个下载过程,因此须要几分钟,可能还会报:Timeout。
    • 镜像自动下载好后会输出这样一段内容,表示已经正常安装并可用了:
    Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 78445dd45222: Pull complete Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://cloud.docker.com/ For more examples and ideas, visit: https://docs.docker.com/engine/userguide/

镜像加速

{
  "registry-mirrors": ["https://ldhc17y9.mirror.aliyuncs.com"] }
  • sudo systemctl daemon-reload
  • sudo systemctl restart docker
  • 在之后的生活中若是要常用阿里云作为本身仓库,那你还须要作:
    • 在 namespace管理 中建立属于你本身的 namespace:https://cr.console.aliyun.com/#/namespace/index
    • 建立镜像仓库:https://cr.console.aliyun.com/#/imageList
      • 建立好仓库后,点击:管理 进入查看仓库的更多详细信息,这里面有不少有用的信息,包括一个详细的操做指南,这份指南等下会用到。
      • 好比我本身建立一个 redis-to-cluster 仓库,地址是阿里云给咱们的:registry.cn-shenzhen.aliyuncs.com/youmeek/redis-to-cluster
      • 那我登陆这个镜像地址的方式:
docker login registry.cn-shenzhen.aliyuncs.com
会让我输入
Username:阿里云邮箱
password:上文提到的--Registry登陆密码
docker login

docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/youmeek/redis-to-cluster:[镜像版本号]

docker push registry.cn-shenzhen.aliyuncs.com/youmeek/redis-to-cluster:[镜像版本号]

Docker 命令,最终部署 Spring Boot 项目

  • 建议:初期使用的时候尽可能用容器 ID / 镜像 ID。若是使用 Tag/Name 在东西多的状况下很容易混乱 还不如就用记不住可是确定惟一的容器 ID / 镜像 ID

重要的基本概念

  • 能够表明一个完整的镜像名有两种方式:
    • REPOSITORY(仓库):TAG(标签)
      • 其中 TAG 表面上不是必须有的,本质是 docker 帮你用 latest 来代替了。latest 这里最好翻译为默认,而不是最新。
    • IMAGE ID(镜像ID)
      • 这是一个 Docker 随机给你生成 数字+字母 的字符串

部署一个 Spring Boot 的 Java Web 项目为例

  • 宿主机环境说明:
    • IP 地址:http://192.168.137.128
    • 中止了防火墙:systemctl stop firewalld.service ; systemctl stop iptables.service
    • 中止防火墙后重启 Docker 服务:systemctl restart docker.service
    • JDK(jdk-8u121-linux-x64.tar.gz)、jar 应用(spring-boot-my-demo.jar),存放宿主机位置:/opt/setups
    • Spring Boot 的 jar 应用中配置文件给的端口是:8080,常规状况下的访问路径:http://127.0.0.1:8080/youmeek
  • 下载镜像:docker pull centos:6.8,个人 IMAGE_ID 为:0cd976dc0a98
  • 运行镜像,实例化为一个容器:docker run -i -t -v /opt/setups:/opt 0cd976dc0a98 /bin/bash
    • -v:表示须要将本地宿主机的目录挂载到容器中对应的一个目录上,格式:-v <宿主机目录>:<容器目录>,因此此时对容器此目录的操做,也是等同于对宿主机的目录的操做
  • 在容器里安装 Oracle JDK 八、配置 JDK 环境变量这里很少说,具体看:JDK 安装
  • 把容器中 /opt 目录下的 spring-boot-my-demo.jar 拷贝到容器的 root 目录下:cp /opt/spring-boot-my-demo.jar /root
  • 再容器里新建脚本:vi /root/spring-boot-run.sh,脚本内容以下:
#!/bin/bash source /etc/profile java -jar /root/spring-boot-my-demo.jar
  • 在容器中对新建脚本增长执行权限:chmod u+x /root/spring-boot-run.sh
  • 咱们启动另一个终端
  • 查看咱们刚刚运行的容器相关信息:docker ps -a
    • 咱们看到了咱们刚刚运行的容器 ID(CONTAINER ID)为:a5d544d9b6f9,这个下面要用到
  • 基于刚刚运行的容器建立新镜像:docker commit a5d544d9b6f9 youmeek/springboot:0.1
    • 查看如今的镜像库:docker images,会发现多了一个 youmeek/springboot 新镜像,镜像 ID 为:7024f230fef9
  • 运行新镜像,实例化为一个容器,并启动容器中刚刚写的脚本:docker run -d -p 38080:8080 --name=springBootJar --hostname=springBootJar 7024f230fef9 /root/spring-boot-run.sh
    • -d:表示以“守护模式”执行 spring-boot-run.sh 脚本,此时 jar 中的 log 日志不会出如今输出终端上。
    • -p:表示宿主机与容器的端口映射,此时将容器内部的 8080 端口映射为宿主机的 38080 端口,这样就向外界暴露了 38080 端口,可经过 Docker 网桥来访问容器内部的 8080 端口了。
    • --name:表示给新实例容器取的名称,用一个有意义的名称命名便可
  • 查看其实运行的容器:docker ps -a,能够知道咱们的新容器 ID:fd21ac056343,名称为:springBootJar
  • 查看这个容器的 jar 应用的 log 输出:docker logs -f fd21ac056343,能够看到 jar 启动后的 log 输出内容
  • 经过浏览器访问容器中的应用:http://192.168.137.128:38080/youmeek/,能够看到 jar 应用的首页能够访问

Docker 基本命令

版本信息

  • docker version,查看docker版本
  • docker info,显示docker系统的信息

镜像仓库

  • docker pull:从仓库下载镜像到本地
    • docker pull centos:latest:获取 CentOS 默认版本镜像
    • docker pull centos:7.3.1611:获取 CentOS 7 镜像,下载大小 70M 左右,下面的操做基于此镜像
    • docker pull centos:6.8:获取 CentOS 6 镜像
    • docker pull registry.cn-hangzhou.aliyuncs.com/chainone/centos7-jdk8:获取别人作好的阿里云镜像
  • docker push:将一个镜像 push 到 registry 仓库中
    • docker push myapache:v1
  • docker search:从 registry 仓库搜索镜像
    • docker search -s 3 centos,参数 -s 数字:表示筛选出收藏数(stars值)大于等于 3 的镜像
  • docker login:登陆到一个镜像仓库。默认登陆的是官网的仓库:https://hub.docker.com

本地镜像管理

  • docker stats:查看当前启动的容器各自占用的系统资源
    • bin docker stats --no-stream kafkadocker_kafka_1 kafkadocker_zookeeper_1:查看指定容器的占用资源状况
    • 更加高级的监控方式有一个软件叫作:ctop(推荐使用):https://github.com/bcicen/ctop
CONTAINER ID        NAME                      CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
4532a9ee27b8        cloud-cadvisor            1.49%               53.28MiB / 3.702GiB   1.41%               13.5MB / 646MB      265MB / 0B          19
3895d5d50a5e        kafkadocker_kafka_1       1.45%               1.24GiB / 3.702GiB    33.51%              145MB / 186MB       499MB / 724MB       128
1d1a6a7c48d8        kafkadocker_zookeeper_1   0.11%               70.85MiB / 3.702GiB   1.87%               55.8MB / 33.7MB     209MB / 1.22MB      23
  • docker images:显示本地全部的镜像列表
    • 关注 REPOSITORY(名称),TAG(标签),IMAGE ID(镜像ID)三列
  • docker images centos:查看具体镜像状况
  • docker rmi:删除镜像,通常删除镜像前要先删除容器,否则若是镜像有被容器调用会报错
    • docker rmi 容器ID:删除具体某一个镜像
    • docker rmi 仓库:Tag:删除具体某一个镜像
    • docker rmi $(docker images -q),删除全部镜像
    • docker rmi -f $(docker images -q),强制删除全部镜像
    • docker rmi $(docker images | grep "vmware" | awk '{print $3}'),批量删除带有 vmware 名称的镜像
  • docker tag:为镜像打上标签
    • docker tag -f ubuntu:14.04 ubuntu:latest,-f 意思是强制覆盖
    • 同一个IMAGE ID可能会有多个TAG(可能还在不一样的仓库),首先你要根据这些 image names 来删除标签,当删除最后一个tag的时候就会自动删除镜像;
    • docker rmi 仓库:Tag,取消标签(若是是镜像的最后一个标签,则会删除这个镜像)
  • docker build:使用 Dockerfile 建立镜像(推荐)
    • docker build . --rm -t runoob/ubuntu:v1,参数 -t,表示:-tag,打标签
    • 屡次 docker build 过程当中是有依赖一个缓存的过程的,通常 build 过程都有好几个 step,Docker 很是聪明,会本身判断那些没有被修改过程的 step 采用缓存。若是想要避免使用缓存,可使用这样命令 --no-cache:docker build --no-cache . --rm -t runoob/ubuntu:v1
  • docker history:显示生成一个镜像的历史命令,能够看出这个镜像的构建过程,包括:每一层镜像的 ID、指令
  • docker save:将一个镜像保存为一个 tar 包,带 layers 和 tag 信息(导出一个镜像)
    • docker save 镜像ID -o /opt/test.tar
  • docker load:从一个 tar 包建立一个镜像(导入一个镜像)
    • docker load -i /opt/test.tar

容器生命周期管理

  • docker run,运行镜像
    • docker run -v /java_logs/:/opt/ -d -p 8080:80 --name=myDockerNameIsGitNavi --hostname=myDockerNameIsGitNavi -i -t 镜像ID /bin/bash
      • -i -t 分别表示保证容器中的 STDIN 开启,并分配一个伪 tty 终端进行交互,这两个是合着用。
      • --name 是给容器起了一个名字(若是没有主动给名字,docker 会自动给你生成一个)容器的名称规则:大小写字母、数字、下划线、圆点、中横线,用正则表达式来表达就是:[a-zA-Z0-9_*-]
      • -d 容器运行在后台。
      • -p 8080:80 表示端口映射,将宿主机的8080端口转发到容器内的80端口。(若是是 -P 参数,则表示随机映射应该端口,通常用在测试的时候)
      • -v /java_logs/:/opt/ 表示目录挂载,/java_logs/ 是宿主机的目录,/opt/ 是容器目录
    • docker run --rm --name=myDockerNameIsGitNavi --hostname=myDockerNameIsGitNavi -i -t centos /bin/bash,--rm,表示退出即删除容器,通常用在作实验测试的时候
    • docker run --restart=always -i -t centos /bin/bash,--restart=always 表示中止后会自动重启
    • docker run --restart=on-failure:5 -i -t centos /bin/bash,--restart=on-failure:5 表示中止后会自动重启,最多重启 5 次
  • docker exec:对守护式的容器里面执行命令,方便对正在运行的容器进行维护、监控、管理
    • docker exec -i -t 容器ID /bin/bash,进入正在运行的 docker 容器,并启动终端交互
    • docker exec -d 容器ID touch /opt/test.txt,已守护式的方式进入 docker 容器,并建立一个文件
  • docker stop 容器ID,中止容器
    • docker stop $(docker ps -a -q),中止全部容器
    • docker stop $(docker ps -a -q) ; docker rm $(docker ps -a -q),中止全部容器,并删除全部容器
    • docker kill $(docker ps -q) ; docker rm $(docker ps -a -q),中止全部容器,并删除全部容器
  • docker start 容器ID,从新启动已经中止的容器(从新启动,docker run 参数仍是保留以前的)
  • docker restart 容器ID,重启容器
  • docker rm,删除容器
    • docker rm 容器ID,删除指定容器(该容器必须是中止的)
    • docker rm -f 容器ID,删除指定容器(该容器若是正在运行能够这样删除)
    • docker rm $(docker ps -a -q),删除全部容器
    • docker rm -f $(docker ps -a -q),强制删除全部容器
    • docker ps -a | grep 'weeks ago' | awk '{print $1}' | xargs docker rm 删除老的(一周前建立)容器
    • docker kill $(docker ps -q) ; docker rm $(docker ps -a -q) ; docker rmi $(docker images -q -a) 中止全部容器,删除全部容器,删除全部镜像
  • docker commit,把容器打成镜像
    • docker commit 容器ID gitnavi/docker-nodejs-test:0.1
      • gitnavi 是你注册的 https://store.docker.com/ 的名字,若是你没有的话,那须要先注册
      • docker-nodejs-test 是你为该镜像起的名字
      • 0.1 是镜像的版本号,默认是 latest 版本
    • docker commit -m="这是一个描述信息" --author="GitNavi" 容器ID gitnavi/docker-nodejs-test:0.1
      • 在提交镜像时指定更多的数据(包括标签)来详细描述所作的修改
  • docker diff 容器ID:显示容器文件系统的先后变化
  • --link 同一个宿主机下的不一样容器的链接:
    • docker run -it 镜像ID --link redis-name:myredis /bin/bash
      • redis-name 是容器名称
      • myredis 是容器别名,其余容器链接它能够用这个别名来写入到本身的配置文件中
  • 容器与宿主机之间文件的拷贝
    • docker cp /www/runoob 96f7f14e99ab:/www/ 将主机 /www/runoob 目录拷贝到容器 96f7f14e99ab 的 /www 目录下
    • docker cp /www/runoob 96f7f14e99ab:/www 将主机 /www/runoob 目录拷贝到容器 96f7f14e99ab 中,目录重命名为 www。
    • docker cp 96f7f14e99ab:/www /tmp/ 将容器96f7f14e99ab的/www目录拷贝到主机的/tmp目录中。

docker 网络模式

  • 查看也有网络:docker network ls
  • 建立网络:docker network create --subnet=172.19.0.0/16 net-redis-to-cluster
  • 已有容器链接到某个网络(一个容器能够同时连上多个网络):docker network connect net-redis-to-cluster my-redis-container
  • 若是是内网提供服务的,能够直接建立一个网络,其服务使用该网络。而后另一个须要调用该服务的,而且是对外网提供服务的可使用 host 模式
  • --network XXXXXX 常见几种模式
    • bridge 默认模式,在 docker0 的网桥上建立新网络栈,确保独立的网络环境,实现网络隔离:docker run -it 镜像ID --network=bridge /bin/bash
    • none 不适用网卡,不会有 IP,没法联网:docker run -it 镜像ID --network=none /bin/bash
    • host 使用宿主机网络 IP、端口联网(在容器里面输入:ip a,看到的结果和在宿主机看到的同样):docker run -it 镜像ID --network=host /bin/bash
    • 自定义-使用本身命名的网络栈,可是须要手动配置网卡、IP 信息:docker run -it 镜像ID --network=自定义名称 /bin/bash

容器管理操做

  • docker ps:列出当前全部 正在运行 的容器
    • docker ps -a:列出全部的容器(包含历史,即运行过的容器)
    • docker ps -l:列出最近一次启动的container
    • docker ps -q:列出最近一次运行的container ID
    • docker ps -a -l:列出最后一次运行的容器
    • docker ps -n x:显示最后 x 个容器,无论是正在运行或是已经中止的
  • docker top 容器ID:显示容器的进程信息
  • docker events:获得 docker 服务器的实时的事件
  • docker logs -f 容器ID:查看容器日志(若是一些容器不断重启,或是自动中止,能够这样看下)
    • docker logs 容器ID,获取守护式容器的日志
    • docker logs -f 容器ID,不断监控容器日志,相似 tail -f
    • docker logs -ft 容器ID,在 -f 的基础上又增长 -t 表示为每条日志加上时间戳,方便调试
    • docker logs --tail 10 容器ID,获取日志最后 10 行
    • docker logs --tail 0 -f 容器ID,跟踪某个容器的最新日志而没必要读取日志文件
    • docker logs -f -t --since="2018-05-26" --tail=200 容器ID 根据某个时间读取日志
    • docker logs -f -t --since="2018-05-26T11:13:40" --tail=200 容器ID 根据某个时间读取日志
    • docker logs -f -t --since="2018-05-25T11:13:40" --until "2018-05-26T11:13:40" --tail=200 容器ID 根据某个时间读取日志
    • docker logs --since 10m 容器ID 查看最近 10 分钟的日志
      • -f : 表示查看实时日志
      • -t : 显示时间戳
      • -since : 显示某个开始时间的全部日志
      • -tail=200 : 查看最后的 200 条日志
  • docker wait,阻塞到一个容器,直到容器中止运行
  • docker export,将容器整个文件系统导出为一个tar包,不带layers、tag等信息
  • docker port,显示容器的端口映射
  • docker inspect 容器ID:查看容器的全面信息,用 JSON 格式输出
  • docker inspect network名称:查看 network 信息,用 JSON 格式输出,包含使用该网络的容器有哪些
  • docker system df:相似于 Linux 上的 df 命令,用于查看 Docker 的磁盘使用状况
    • Images 镜像
    • Containers 容器
    • Local Volumes 数据卷
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              6                   6                   1.049GB             0B (0%)
Containers          7                   4                   10.25kB             0B (0%)
Local Volumes       13                  5                   38.49GB             1.365MB (0%)
Build Cache                                                 0B                  0B
获取容器中的 IP:docker inspect -f {{.NetworkSettings.IPAddress}} 容器ID
获取容器中的 IP:docker inspect -f {{.Volumes}} 容器ID
查看容器的挂载状况:docker inspect 容器ID | grep Mounts -A 10
  • 下面为一个 docker inspect 后的结果示例:
[
    {
        "Id": "e1dff77b99d9c8489e0a0ce68a19ec5ffe18cc5d8b8ec17086f7f7bea29aa09b", "Created": "2018-01-18T03:47:16.138180181Z", "Path": "docker-entrypoint.sh", "Args": [ "--auth" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 19952, "ExitCode": 0, "Error": "", "StartedAt": "2018-01-18T03:47:16.348568927Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:42aa46cfbd7a0d1101311defac39872b447b32295b40f9c99104ede5d02e9677", "ResolvConfPath": "/var/lib/docker/containers/e1dff77b99d9c8489e0a0ce68a19ec5ffe18cc5d8b8ec17086f7f7bea29aa09b/resolv.conf", "HostnamePath": "/var/lib/docker/containers/e1dff77b99d9c8489e0a0ce68a19ec5ffe18cc5d8b8ec17086f7f7bea29aa09b/hostname", "HostsPath": "/var/lib/docker/containers/e1dff77b99d9c8489e0a0ce68a19ec5ffe18cc5d8b8ec17086f7f7bea29aa09b/hosts", "LogPath": "/var/lib/docker/containers/e1dff77b99d9c8489e0a0ce68a19ec5ffe18cc5d8b8ec17086f7f7bea29aa09b/e1dff77b99d9c8489e0a0ce68a19ec5ffe18cc5d8b8ec17086f7f7bea29aa09b-json.log", "Name": "/cas-mongo", "RestartCount": 0, "Driver": "overlay", "Platform": "linux", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, "HostConfig": { "Binds": [ "/data/mongo/db:/data/db" ], "ContainerIDFile": "", "LogConfig": { "Type": "json-file", "Config": {} }, "NetworkMode": "default", "PortBindings": { "27017/tcp": [ { "HostIp": "", "HostPort": "27017" } ] }, "RestartPolicy": { "Name": "always", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "shareable", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "runc", "ConsoleSize": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": [], "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DeviceCgroupRules": null, "DiskQuota": 0, "KernelMemory": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": null, "OomKillDisable": false, "PidsLimit": 0, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0 }, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay/0ab08b1f9c8f5f70cdcac2b01d9ee31de9e5a4955003567573635e8837931249/root", "MergedDir": "/var/lib/docker/overlay/4d6bb0d57f3f1b1dcf98c70b4bee4abf8dc110c7efa685ee5d84fe6f58c07b63/merged", "UpperDir": "/var/lib/docker/overlay/4d6bb0d57f3f1b1dcf98c70b4bee4abf8dc110c7efa685ee5d84fe6f58c07b63/upper", "WorkDir": "/var/lib/docker/overlay/4d6bb0d57f3f1b1dcf98c70b4bee4abf8dc110c7efa685ee5d84fe6f58c07b63/work" }, "Name": "overlay" }, "Mounts": [ { "Type": "volume", "Name": "6cd9721ff6a2768cd20e4a0678b176fa81a5de1c7d21fe6212b50c6854196db2", "Source": "/var/lib/docker/volumes/6cd9721ff6a2768cd20e4a0678b176fa81a5de1c7d21fe6212b50c6854196db2/_data", "Destination": "/data/configdb", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }, { "Type": "bind", "Source": "/data/mongo/db", "Destination": "/data/db", "Mode": "", "RW": true, "Propagation": "rprivate" } ], "Config": { "Hostname": "e1dff77b99d9", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "27017/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "GOSU_VERSION=1.7", "GPG_KEYS=0C49F3730359A14518585931BC711F9BA15703C6", "MONGO_PACKAGE=mongodb-org", "MONGO_REPO=repo.mongodb.org", "MONGO_MAJOR=3.4", "MONGO_VERSION=3.4.10" ], "Cmd": [ "--auth" ], "Image": "mongo:3.4", "Volumes": { "/data/configdb": {}, "/data/db": {} }, "WorkingDir": "", "Entrypoint": [ "docker-entrypoint.sh" ], "OnBuild": null, "Labels": {} }, "NetworkSettings": { "Bridge": "", "SandboxID": "7eabf418238f4d9f5fd5163fd4d173bbaea7764687a5cf40a9757d42b90ab2f9", "HairpinMode": false, "Link LocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "27017/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "27017" } ] }, "SandboxKey": "/var/run/docker/netns/7eabf418238f", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "11c8d10a4be63b4ed710add6c440adf9d090b71918d4aaa837c46258e5425b80", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "ada97659acda146fc57e15a099e430a6e97de87f6d043b91d4c3582f6ab52d47", "EndpointID": "11c8d10a4be63b4ed710add6c440adf9d090b71918d4aaa837c46258e5425b80", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null } } } } ]

Docker 容器产生的 log 位置

  • Docker 运行一段时间,若是你的容器有大量的输出信息,则这个 log 文件会很是大,因此要考虑清理。
  • log 位置:/var/lib/docker/containers/容器ID值/容器ID值-json.log
  • 能够考虑在停到容器的时候备份这个文件到其余位置,而后:echo > 容器ID值-json.log
  • 固然,官网也提供了自动化的方案:https://docs.docker.com/config/containers/logging/json-file/
    • 修改 Docker 是配置文件:vim /etc/docker/daemon.json,(若是没有这个文件,本身新增)增长以下内容:
{
  "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" } }
  • 若是你已经有该文件文件莱使用国内源,那修改方案应该是这样的:
{
	"registry-mirrors": ["https://ldhc17y9.mirror.aliyuncs.com"], "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" } }

删除 Docker 镜像中为 none 的镜像

  • Dockerfile 代码更新频繁,天然 docker build 构建同名镜像也频繁的很,产生了众多名为 none 的无用镜像
docker rmi $(docker images -f "dangling=true" -q)

Docker daemon.json 可配置参数

Docker remote api 远程操做配置(保证在内网环境)

  • 假设要被远程操做的服务器 IP:192.168.1.22
  • 修改其配置文件:vim /lib/systemd/system/docker.service
  • 修改默认值为:ExecStart=/usr/bin/dockerd
  • 改成:ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376
    • 若是还须要连本身的 harbor 这类,完整配置:ExecStart=/usr/bin/dockerd --insecure-registry harbor.youmeek.com -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376
  • systemctl daemon-reload
  • systemctl reload docker
  • systemctl restart docker
  • 验证:
    • 在其余服务器上运行:docker -H 192.168.1.22:2376 images
    • 能拿到和它自己看到的同样的数据表示能够了

Dockerfile 解释

  • 该文件名就叫 Dockerfile,注意大小写,没有后缀,不然会报错。
  • 主要由下面几个部分组成:
    • 基础镜像信息
    • 维护者/建立者信息
    • 镜像操做指令
    • 容器启动时执行执行
  • 注释符号:# 这是一段注释说明
  • 经常使用指令关键字:
    • FROM,基础镜像信息
    • MAINTAINER,维护者/建立者信息
    • ADD,添加文件。若是添加的文件是相似 tar.gz 压缩包,会自动解压。
      • 特别注意的是:ADD 文件到镜像的地址若是是目录,则须要最后保留斜杠,好比:ADD test.tar.gz /opt/shell/。不是斜杠结尾会认为是文件。
      • 添加文件格式:ADD test.sh /opt/shell/test.sh
      • 添加压缩包并解压格式:ADD test.tar.gz /opt/shell/,该压缩包会自动解压在 /opt/shell 目录下
    • COPY,相似 ADD,只是 COPY 只是复制文件,不会作相似解压压缩包这种行为。
      • COPY /opt/conf/ /etc/ 把宿主机的 /opt/conf 下文件复制到镜像的 /etc 目录下。
    • WORKDIR,设置工做目录,能够理解为相似 cd 命令,表示如今在某个目录路径,而后下面的 CMD、ENTRYPOINT 操做都是基于此目录
    • VOLUME,目录挂载
    • EXPOSE,暴露端口
    • USER,指定该镜像以什么用户去运行,也能够用这个来指定:docker run -u root。不指定默认是 root
    • ENV,定义环境变量,该变量能够在后续的任何 RUN 指令中使用,使用方式:$HOME_DIR。在 docker run 的时候能够该方式来覆盖变量值 docker run -e “HOME_DIR=/opt”
    • RUN,执行命令并建立新的镜像层,RUN 常常用于安装软件包
    • CMD,执行命令,而且一个 Dockerfile 只能有一条 CMD,有多条的状况下最后一条有效。在一种场景下 CMD 命令无效:docker run 的时候也指定了相同命令,则 docker run 命令优先级最高
    • ENTRYPOINT,配置容器启动时运行的命令,不会被 docker run 指令覆盖,而且 docker run 的指令能够做为参数传递到 ENTRYPOINT 中。要覆盖 ENTRYPOINT 命令也是有办法的:docker run --entrypoint 方式。Dockerfile 同时有 CMD 和 ENTRYPOINT 的时候,CMD 的指令是做为参数传递给 ENTRYPOINT 使用。
      • 特别注意:RUN、CMD 和 ENTRYPOINT 这三个 Dockerfile 指令看上去很相似,很容易混淆。
      • 最佳实战:来源
        • 使用 RUN 指令安装应用和软件包,构建镜像。
        • 若是 Docker 镜像的用途是运行应用程序或服务,好比运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。
        • 若是想为容器设置默认的启动命令,可以使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。

Dockerfile 部署 Spring Boot 应用

  • jar 名称:skb-user-0.0.1-SNAPSHOT.jar
  • 打算用的宿主机端口:9096
  • Dockerfile 文件和 jar 文件存放在宿主机目录:/opt/zch
  • Dockerfile 内容以下:
FROM java:8-jre
MAINTAINER gitnavi <gitnavi@qq.com> ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone ADD skb-user-0.0.1-SNAPSHOT.jar /usr/local/skb/user/ CMD ["java", "-Xmx500m", "-jar", "/usr/local/skb/user/skb-user-0.0.1-SNAPSHOT.jar", "--spring.profiles.active=test"] EXPOSE 9096
  • 开始构建:
    • cd /opt/zch
    • docker build . --tag="skb/user:v1.0.1"
      • 由于 build 过程当中会有多层镜像 step 过程,因此若是 build 过程当中失败,那解决办法的思路是找到 step 失败的上一层,成功的 step 中镜像 ID。而后 docker run 该镜像 ID,手工操做,看报什么错误,而后就比较清晰得了解错误状况了。
    • docker run -d -p 9096:9096 -v /usr/local/logs/:/opt/ --name=skbUser --hostname=skbUser skb/user:v1.0.1
    • 查看启动后容器列表:docker ps
    • jar 应用的日志是输出在容器的 /opt 目录下,由于咱们上面用了挂载,所在在咱们宿主机的 /usr/local/logs 目录下能够看到输出的日志
  • 防火墙开放端口:
    • firewall-cmd --zone=public --add-port=9096/tcp --permanent
    • firewall-cmd --reload
  • 解释:
# 是为了解决容器的时区和宿主机不一致问题
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

Dockerfile 部署 Tomcat 应用

  • 编写 Dockerfile
FROM tomcat:8.0.46-jre8
MAINTAINER GitNavi <gitnavi@qq.com>

ENV JAVA_OPTS="-Xms2g -Xmx2g -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=312M"
ENV CATALINA_HOME /usr/local/tomcat

ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN rm -rf /usr/local/tomcat/webapps/*

ADD qiyeweixin.war /usr/local/tomcat/webapps/

EXPOSE 8080

CMD ["catalina.sh", "run"]
  • 打包镜像:docker build -t harbor.gitnavi.com/demo/qiyeweixin:1.2.2 ./
  • 运行:docker run -d -p 8888:8080 --name=qiyeweixin --hostname=qiyeweixin -v /data/docker/logs/qiyeweixin:/data/logs/qiyeweixin harbor.gitnavi.com/demo/qiyeweixin:1.2.2
  • 带 JVM 参数运行:docker run -d -p 8888:8080 -e JAVA_OPTS='-Xms7g -Xmx7g -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=512M' --name=qiyeweixin --hostname=qiyeweixin -v /data/docker/logs/qiyeweixin:/data/logs/qiyeweixin harbor.gitnavi.com/demo/qiyeweixin:1.2.2
    • 虽然 Dockerfile 已经有 JVM 参数,而且也是有效的。可是若是 docker run 的时候又带了 JVM 参数,则会以 docker run 的参数为准
  • 测试 JVM 是否有效方法,在代码里面书写,该值要接近 xmx 值:
long maxMemory = Runtime.getRuntime().maxMemory();
logger.warn("-------------maxMemory=" + ((double) maxMemory / (1024 * 1024)));

Docker Compose

  • Docker Compose 主要用于定义和运行多个 Docker 容器的工具,这样能够快速运行一套分布式系统
    • 容器之间是有依赖关系,好比我一个 Java web 系统依赖 DB 容器、Redis 容器,必须这些依赖容器先运行起来。
  • 一个文件:docker-compose.yml
  • 一个命令:docker-compose up
    • 指定文件:docker-compose -f zookeeper.yml -p zk_test up -d
  • 官网安装说明:https://docs.docker.com/compose/install/#install-compose
  • 安装方法:
sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose
  • 检查是否安装成功:docker-compose --version,输出:docker-compose version 1.18.0, build 8dd22a9
  • 经常使用命令:
    • 运行:docker-compose up -d
    • 中止运行:docker-compose down
    • 查看容器:docker-compose ps
    • 删除中止的服务容器:docker-compose rm

Docker Swarm

  • Docker Swarm 是一个 Docker 集群管理工具

Harbor 镜像私有仓库

相关文章
相关标签/搜索