通俗的说,虚拟化就是把物理资源转变为逻辑上可以管理的资源,以打破物理结构间的壁垒,计算元件运行在虚拟的基础上而不是真实的基础上,可以扩大硬件的容量,简化软件的重新配置过程。
允许一个平台同时运行多个操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率,是一个为了简化管理,优化资源的解决方案。
目前主流的虚拟化技术主要有:KVM、Xen、VMware Esxi、VirtualBox、Docker,虚拟化技术也越来越广泛的应用在企业中,例如Taobao、Google等。
虚拟化原理:虚拟化解决方案的底部是要进行虚拟化的物理机器,这台机器可能直接支持虚拟化,也可能不会直接支持虚拟化,那么就需要系统管理程序层的支持。
系统管理程序(Virtual machine monitor),或称为 VMM,可以看作是平台硬件和操作系统的抽象化。在某些情况中,这个系统管理程序就是一个操作系统,此时它就称为主机操作系统。
图 1. 虚拟化的分层抽象
完全拟化技术实际上是通过软件实现对操作系统的资源再分配,比较成熟,例如我们的KVM、VirtualBOX;
半虚拟化技术则是通过代码修改已有的系统,形成一种新的可虚拟化的系统,调用硬件资源去安装多个系统,整体速度上相对高一点,代表产品有Xen。
轻量级虚拟化,Docker虚拟化(介于完全虚拟化、半虚拟化之间),轻量级虚拟化;
Docker技术类似集装箱,最早集装箱没有出现的时候,码头上有许多搬运的工人在搬运货物,集装箱出现以后,码头上看到更多的不是工人,而且集装箱的搬运模式更加单一,更加高效,还有其他的好处。
例如:货物多打包在集装箱里面,可以防止货物之间相互影响。并且到了另外一个码头需要转运的话,有了集装箱以后,直接把它运送到另一个容器内即可,完全可以保证里面的货物是整体的搬迁,并且不会损坏货物本身。如图所示:
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架或包括系统。
Docker应该是近年最火爆的技术之一,如果没有听说过,那么你就out了,2018年将开启新的跨越。
Docker 自开源后受到广泛的关注和讨论,以至于 dotCloud 公司后来都改名为 Docker Inc。Redhat 已经在其 RHEL6.5 中集中支持Docker;Google 也在其 PaaS 产品中广泛应用。
Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。在LXC的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。
下面对比了Docker 和传统虚拟化(KVM、XEN等)方式的不同之处,Docker容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件的基础上,虚拟出自己的系统,再在系统上部署相关的APP应用。
Docker虚拟化有三个概念需要理解,分别镜像、容器、仓库。
镜像:Docker的镜像其实就是模板,跟我们常见的ISO镜像类似,是一个样板。
容器:使用镜像常见的应用或者系统,我们称之为一个容器。
仓库:仓库是存放镜像的地方,分为公开仓库(Public)和私有仓库(Private)两种形式。
运行时的性能可以获取极大提升,管理操作(启动,停止,开始,重启等等) 都是以秒或毫秒为单位的。
你会拥有足够的“操作系统”,仅需添加或减小镜像即可。在一台服务器上可以布署100~1000个Containers容器。但是传统虚拟化,你虚拟10-20个虚拟机就不错了。
开源的,免费的,低成本的。由现代Linux内核支持并驱动。注*
轻量的Container必定可以在一个物理机上开启更多“容器”,注定比VMs要便宜。
正在越来越受欢迎,包括各大主流公司都在推动docker的快速发展,性能有很大的优势。
目前知道的人比较少; 相关的中文技术资料欠缺; Go语言还未完全成熟。
- Docker在整个开发周期都可以完美的辅助你实现快速交付。Docker允许开发者在装有应用和服务本地容器做开发。可以直接集成到可持续开发流程中。
- 开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。
- Docker容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。
- Docker的兼容性和轻量特性可以很轻松的实现负载的动态管理。你可以快速扩容或方便的下线的你的应用和服务,这种速度趋近实时。
- Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker容器。容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
- 使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。
- Docker Client:客户端
用户与Docker交互的主要方式,Docker客户端可以与多个守护进程进行交互- Docker Daemon:守护进程
用来监听Docker API的请求并管理对象,例如镜像、容器、网络和卷,守护进程还可以与其他的守护进程通信以管理Docker服务- Docker Image:镜像
Docker镜像是一个只读模板,包含创建Docker容器的说明,通常一个镜像基于另一个镜像,并带有一些额外的自定义镜像,可以自定义创建一个镜像,也可以使用其他人再Docker仓库创建发布的镜像- Docker Container:容器
容器是镜像可以运行的实例,可以通过Docker API或者客户端创建、启动、停止、移动或者删除容器,可以将容器连接到一个或者多个网络,将存储附加到该网络中,也可以根据当前的状态进行创建新的镜像- Docker Registry:镜像仓库
Docker仓库用来存储Docker的镜像,Docker Hub是任何人都可以使用的Docker镜像仓库,Docker配置项也默认在这上面查找镜像
- 镜像分层,每个镜像都由一个或多个镜像层组成;
- 可通过在某个镜像加上一定的镜像层得到新镜像(此过程可通过编写dockerfile或基于容器Commit实现);
- 每个镜像层拥有唯一镜像ID; 镜像在存储和使用时共享相同的镜像层(根据ID),所以在pull镜像时,已有的镜像层会自动跳过下载;
- 每个镜像层都是只读,即使启动成容器,也无法对其真正的修改,修改只会作用于最上层的容器层;
##关闭selinux
setenforce 0
sed -i '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config
##安装依赖包
yum -y install yum-utils device-mapper-persistent-data lvm2
##配置docker镜像源
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
##安装docker
yum -y install docker-ce
systemctl start docker
systemctl enable docker
Docker默认连接的国外官方镜像,通常根据网络情况不同,访问时快时慢,大多时候获取速度非常慢,为了提示效率可以自建仓库或者先修改为国内仓库源,提升拉取镜像的速度。
Docker可以配置的国内镜像有很多可供选择,例如:Docker中国区官方镜像、阿里云、网易蜂巢、DaoCloud等,这些都是国内比较快的镜像仓库。
从国外官网下载Docker Tomcat镜像,访问速度慢,如图所示:
Docker镜像修改方法如下:
cat>/etc/docker/daemon.json<<EOF
{
"registry-mirrors":["https://registry.docker-cn.com"] }
EOF
systemctl restart docker
要使用docker虚拟化,需要下载镜像,使用docker命令启动,为了好让大家理解,这里直接利用docker启动centos系统。
公共仓库下载centos镜像:
网络比较慢,可以下载好,然后导入镜像也可以,如下为Docker常用命令详解:
命令 | 描述 |
---|---|
docker search | 在docker hub中搜索镜像; |
docker pull | 从docker镜像源服务器拉取指定镜像或者库镜像; |
docker push | 推送指定镜像或者库镜像至docker源服务器; |
docker history | 展示一个镜像形成历史; |
docker images | 列出系统当前镜像; |
docker run | 创建一个新的容器并运行一个命令; |
docker start | 启动容器; |
docker stop | 停止容器; |
docker attach | 当前shell下attach连接指定运行镜像; |
docker build | 通过Dockerfile定制镜像; |
docker commit | 提交当前容器为新的镜像; |
docker cp | 从容器中拷贝指定文件或者目录到宿主机中; |
docker create | 创建一个新的容器,同run,但不启动容器; |
docker diff | 查看docker容器变化; |
docker events | 从docker服务获取容器实时事件; |
docker exec | 在已存在的容器上运行命令; |
docker export | 导出容器的内容流作为一个tar归档文件[对应import]; |
docker import | 从tar包中的内容创建一个新的文件系统映像[对应export]; |
docker info | 显示系统相关信息; |
docker inspect | 查看容器详细信息; |
docker kill | 指定docker容器; |
docker load | 从一个tar包中加载一个镜像[对应save]; |
docker login | 注册或者登陆一个docker源服务器; |
docker logout | Dockerregistry退出; |
docker logs | 输出当前容器日志信息; |
docker port | 查看映射端口对应的容器内部源端口; |
docker pause | 暂停容器; |
docker ps | 列出容器列表; |
docker restart | 重启运行的容器; |
docker rm | 移除一个或者多个容器; |
docker rmi | 移除一个或多个镜像; |
docker save | 保存一个镜像为一个tar包[对应load]; |
docker tag | 给源中镜像打标签; |
docker top | 查看容器中运行的进程信息; |
docker unpause | 取消暂停容器; |
docker version | 查看docker版本号; |
docker wait | 截取容器停止时的退出状态值; |
- host模式,使用–net=host指定;
- container模式,使用–net=container:NAME_or_ID指定;
- none模式,使用–net=none指定;
- bridge模式,使用–net=bridge指定,默认设置;
只需要在宿主机pull相关的镜像即可,指令如下:
docker pull uifd/ui-for-docker
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
uifd/ui-for-docker latest 965940f98fa5 5 years ago 8.1MB
docker run -itd --name docker-web -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock uifd/ui-for-docker
docker0: iptables: No chain/target/match by that name.
解决方法:
如上报错信息是因为本地iptables规则策略没有匹配的链表,解决方案如下:
systemctl stop docker
iptables -t nat -F
ifconfig docker0 down
yum install -y bridge* -y
brctl delbr docker0
systemctl start docker
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc5e52023066 uifd/ui-for-docker "/ui-for-docker" 6 minutes ago Up 6 minutes 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp docker-web
- Docker commit|export将新容器提交至Images列表;
- 编写Dockerfile,bulid新的镜像至镜像列表;
- FROM 指定所创建镜像的基础镜像;
- MAINTAINER 指定维护者信息;
- RUN 运行命令;
- CMD 指定启动容器时默认执行的命令;
- LABEL 指定生成镜像的元数据标签信息;
- EXPOSE 声明镜像内服务所监听的端口;
- ENV 指定环境变量;
- ADD 赋值指定的路径下的内容到容器中的路径下,可以为URL;如果为tar文件,会自动解压到路径下
- COPY 赋值本地主机的路径下的内容到容器中的路径下;一般情况下推荐使用COPY而不是ADD;
- ENTRYPOINT 指定镜像的默认入口;
- VOLUME 创建数据挂载点;
- USER 指定运行容器时的用户名或UID;
- WORKDIR 配置工作目录; ARG 指定镜像内使用的参数(例如版本号信息等);
- ONBUILD 配置当前所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作的命令; STOPSIGNAL 容器退出的信号;
- HEALTHCHECK 如何进行健康检查;
- SHELL 指定使用SHELL时的默认SHELL类型;
格式为:FROM<image>,或FROM<image>:<tag>,或FROM<image>@<digest>。
任何Dockerfile中的第一条指令必须为FROM指令。
并且,如果在同一个Dockerfile文件中创建多个镜像,可以使用多个FROM指令(每个镜像一次)。
格式为MAINTAINER<name>。例如:
MAINTAINER [email protected]
该信息将会写入生成镜像的Author属性域中。
格式为:RUN<command>或RUN ["executable","param1","param2"]。
注意:后一个指令会被解析为json数组,所以必须使用双引号。
前者默认将在shell终端中运行命令,即/bin/sh -c;后者则使用exec执行,不会启动shell环境。
指定使用其他终端类型可以通过第二种方式实现,例如:
RUN ["/bin/bash","-c","echo hello"]
每条RUN指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用\换行。例如:
RUN apt-get update \
&& apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \
&& rm -rf /var/cache/apt
CMD ["executable","param1","param2"] 使用exec执行,是推荐使用的方式;
CMD param1 param2 在/bin/sh中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给ENTRYPOINT的默认参数。
每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行。
入股用户启动容器时指定了运行的命令(作为run的参数),则会覆盖掉CMD指定的命令。
格式为:LABEL <key>=<value> <key>=<value> <key>=<value> ...。
例如:
LABEL version="1.0"
LABEL description="This text illustrates \ that label-values can span multiple lines."
格式为:EXPOSE <port> [<port>...]
例如:
EXPOSE 22 80 443 3306
注意:该命令只是起到声明作用,并不会自动完成端口映射。
在容器启动时需要使用-P(大写P),Docker主机会自动分配一个宿主机未被使用的临时端口转发到指定的端口;
使用-p(小写p),则可以具体指定哪个宿主机的本地端口映射过来。
格式为:ENV <key><value>或ENV<key>=<value>...。
例如:
ENV GOLANG_VERSION 1.6.3
ENV GOLANG_DOWNLOAD_RUL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdd5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb
RUN curl -fssL "$GOLANG_DOWNLOAD_RUL" -o golang.tar.gz && echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && tar -C /usr/local -xzf golang.tar.gz && rm golang.tar.gz
ENV GOPATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN mkdir -p "$GOPATH/bin" && chmod -R 777 "$GOPATH"
指令指定的环境变量在运行时可以被覆盖掉,如docker run --env <key>=<value> built_image。
格式为:ADD<src> <dest>
其中<src>可以使Dockerfile所在目录的一个相对路径(文件或目录),也可以是一个URL,还可以是一个tar文件(如果是tar文件,会自动解压到<dest>路径下)。<dest>可以使镜像内的绝对路径,或者相当于工作目录(WORKDIR)的相对路径。路径支持正则表达式,例如:
ADD *.c /code/
ENTRYPOINT ["executable","param1","param2"] (exec调用执行);
ENTRYPOINT command param1 param2(shell中执行)。
此时,CMD指令指定值将作为根命令的参数。
每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个有效。
在运行时可以被--entrypoint参数覆盖掉,如docker run --entrypoint。
格式为:VOLUME ["/data"] 可以从本地主机或者其他容器挂载数据卷。
一般用来存放数据库和需要保存的数据等。
当服务不需要管理员权限时,可以通过该指令指定运行用户,并且可以在之前创建所需要的用户。例如:
RUN groupadd -r nginx && useradd -r -g nginx nginx要临时获取管理员权限可以用gosu或者sudo。
格式为:WORKDIR /path/to/workdir。
可以使用多个WORKDIR指令,后续命令如果参数是相对的,则会基于之前命令指定的路径。例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
则最终路径为/a/b/c
格式为:ARG<name>[=<default value>]。
则可以用docker build --build-arg<name>=<value>来指定参数值。
格式为:ONBUILD [INSTRUCTION]。
例如Dockerfile使用如下的内容创建了镜像image-A:
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
如果基于image-A镜像创建新的镜像时,新的Dockerfile中使用FROM image-A指定基础镜像。
会自动执行ONBUILD指令的内容,等价于在后面添加了两条指令:
FROM image-A
# Automatically run the following
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
使用ONBUILD指令的镜像,推荐在标签中注明,例如:ruby:1.9-onbuild。
HEALTHCHECK [OPTIONS] CMD command :根据所执行命令返回值是否为0判断;HEALTHCHECK NONE:禁止基础镜像中的健康检查。
[OPTION]支持:
--inerval=DURATION (默认为:30s):多久检查一次;
--timeout=DURATION (默认为:30s):每次检查等待结果的超时时间;
--retries=N (默认为:3):如果失败了,重试几次才最终确定失败。
格式为: SHELL ["executable","parameters"]默认值为 ["bin/sh","-c"]。
注意:对于Windows系统,建议在Dockerfile开头添加# escape=`来指定转移信息。
编写Dockerfile之后,可以通过docker build命令来创建镜像。 基本的docker build [选项]
内容路径,该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下的所有内容发送给Docker服务端,由服务端来创建镜像。因此除非生成镜像需要,否则一般建议放置Dockerfile的目录为空目录。
如果使用非内容路径下的Dockerfile,可以通过-f选项来指定其路径; 要指定生成镜像的标签信息,可以使用-t选项。
例如:指定Dockerfile所在路径为
/tmp/docker_builder/,并且希望生成镜像标签为build_repo/first_image,可以使用下面的命令:
docker build -t build_repo/first_image /tmp/docker_builder
使用.dockerignore文件
可以通过.dockeringore文件(每一行添加一条匹配模式)来让Docker忽略匹配模式路径下的目录和文件。例如:
# comment
*/tmp*
*/*/tmp*
tmp?
~*
- 精简镜像用途:尽量让每个镜像的用途都比较集中、单一,避免构造大而复杂、多功能的镜像;
- 选用合适的基础镜像:过大的基础镜像会造成构建出臃肿的镜像,一般推荐比较小巧的镜像作为基础镜像; 提供详细的注释和维护者信息: Dockerfile也是一种代码,需要考虑方便后续扩展和他人使用;
- 正确使用版本号:使用明确的具体数字信息的版本号信息,而非latest,可以避免无法确认具体版本号,统一环境;
- 减少镜像层数:减少镜像层数建议尽量合并RUN指令,可以将多条RUN指令的内容通过&&连接;
- 及时删除临时和缓存文件:这样可以避免构造的镜像过于臃肿,并且这些缓存文件并没有实际用途;
- 提高生产速度:合理使用缓存、减少目录下的使用文件,使用.dockeringore文件等;
- 调整合理的指令顺序:在开启缓存的情况下,内容不变的指令尽量放在前面,这样可以提高指令的复用性;
- 减少外部源的干扰:如果确实要从外部引入数据,需要制定持久的地址,并带有版本信息,让他人可以重复使用而不出错。
# 设置基本的镜像,后续命令都以这个镜像为基础
FROM centos:v1
# 作者信息
MAINTAINER YS.NET
# RUN命令会在上面指定的镜像里执行任何命令
RUN rpm --rebuilddb;yum install passwd openssl openssh-server -y
RUN echo '123456' | passwd --stdin root
RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh
# 暴露ssh端口22
EXPOSE 22
# 设定运行镜像时的默认命令:输出ip,并以daemon方式启动sshd
CMD /usr/sbin/sshd;/bin/bash
基于Dockerfile来创建生成镜像,命令如下:
用docker build根据Dockerfile创建镜像(centos:ssh):
docker build -t centos:ssh - < Dockerfile
docker build -t centos:ssh .
# 设置基本的镜像,后续命令都以这个镜像为基础
FROM centos_lamp:v1
# 作者信息
MAINTAINER JFEDU.NET
# RUN命令会在上面指定的镜像里执行任何命令
RUN rpm --rebuilddb;yum install redis* -y
RUN sed -i '/bind/127.0.0.1/0.0.0.0/g' /etc/redis.conf
#暴露ssh端口6379
EXPOSE 6379
#设定运行以daemon方式启动sshd
CMD /usr/sbin/redis -D
# 设置基本的镜像,后续命令都以这个镜像为基础
FROM centos_lamp:v1
# 作者信息
MAINTAINER JFEDU.NET
# RUN命令会在上面指定的镜像里执行任何命令
RUN rpm --rebuilddb;yum install pcre-devel -y
RUN rpm --rebuilddb;yum install httpd httpd-devel –y
RUN echo “<h1>The Test Page JFEDU</h1>” >>/var/www/html/index.html
#暴露ssh端口80
EXPOSE 80
#启动httpd
CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]
最终截图如下:
FROM centos:v1
RUN groupadd -r mysql && useradd -r -g mysql mysql
RUN rpm --rebuilddb;yum install -y gcc zlib-devel gd-devel
ENV MYSQL_MAJOR 5.6
ENV MYSQL_VERSION 5.6.20
RUN
&& curl -SL "http://dev.mysql.com/get/Downloads/MySQL-$MYSQL_MAJOR/mysql-$MYSQL_VERSION-linux-glibc2.5-x86_64.tar.gz" -o mysql.tar.gz \
&& curl -SL "http://mysql.he.net/Downloads/MySQL-$MYSQL_MAJOR/mysql-$MYSQL_VERSION-linux-glibc2.5-x86_64.tar.gz.asc" -o mysql.tar.gz.asc \
&& mkdir /usr/local/mysql \
&& tar -xzf mysql.tar.gz -C /usr/local/mysql \
&& rm mysql.tar.gz* \
ENV PATH $PATH:/usr/local/mysql/bin:/usr/local/mysql/scripts
WORKDIR /usr/local/mysql
VOLUME /var/lib/mysql
EXPOSE 3306
CMD ["mysqld", "--datadir=/var/lib/mysql", "--user=mysql"]
- 节省网络带宽,针对于每个镜像不用去Docker官网仓库下载;
- 下载Docker镜像从本地私有仓库中下载;
- 组件公司内部私有仓库,方便各部门使用,服务器管理更加统一;
- 可以基于GET或者SVN、Jenkins更新本地Docker私有仓库镜像版本。
(1)下载Docker registry镜像,命令如下:
docker pull docker.io/registry
(2)启动私有仓库容器,启动命令如下:
mkdir -p /data/registry/
docker run -itd -p 5000:5000 -v /data/registry:/var/lib/registry docker.io/registry
(3)上传镜像至本地私有仓库:
客户端上传镜像至本地私有仓库,如下以busybox镜像为例,将busybox上传至私有仓库服务器。
docker pull busybox
docker tag busybox 192.168.0.123:5000/busybox
docker push 192.168.0.123:5000/busybox
(4)检测本地私有仓库:
curl -XGET http://192.168.0.123:5000/v2/_catalog
curl -XGET http://192.168.0.123:5000/v2/busybox/tags/list
(5)客户端使用本地私有仓库:
客户端docker /etc/docker/daemon.json配置文件添加如下代码,同时重启docker服务,获取本地私有仓库如图24-3所示:
OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false --insecure-registry 192.168.0.123:5000'
ADD_REGISTRY='--add-registry 192.168.0.123:5000'
OPTIONS='--storage-opt overlay2.size=40G'
以上方法只适用于新容器生成,并且修改后需要重启docker,无法做到动态给正在运行容器指定大小,如下图为默认容器大小:
修改Docker存储配置文件,加入如下代码:(默认如果已经为overlay2,则无需修改)
vi /etc/sysconfig/docker-storage
DOCKER_STORAGE_OPTIONS="--storage-driver overlay2 "
然后重启docker即可;
Overlay2 Docker磁盘驱动模式,如果要调整其大小,通过如上的方法,会导致Docker引擎服务无法启动,还需要让Linux文件系统设置为xfs,并且支持目录级别的磁盘配额功能;
2)格式化硬盘为xfs文件系统格式,命令如下:
mkfs.xfs -f /dev/sdb
3)创建data目录,后续将作为docker数据目录;
mkdir /data/ -p
4)挂载data目录,并且开启磁盘配额功能(默认xfs支持配额功能);
mount -o uquota,prjquota /dev/sdb /data/
- 根据用户(uquota/usrquota/quota)
- 根据组(gquota/grpquota) ;
- 根据目录(pquota/prjquota)(不能与grpquota同时设定) 。
5)查看配额-配置详情,命令如下:
xfs_quota -x -c 'report' /data/
6)可以通过命令xfs_quota设置来为用户和目录分配配额,也可以通过命令来查看配额信息;
xfs_quota -x -c 'limit bsoft=10M bhard=10M jfedu' /data
xfs_quota -x -c 'report' /data/
7)将docker引擎默认数据存储目录:/var/lib/docker重命名,并且将/data/docker目录软链接至/var/lib/下即可;
mkdir -p /data/docker/
cd /var/lib/
mv docker docker.bak
ln -s /data/docker/ .
8)重启Docker服务,并且查看进程,可以看到docker overlay2.size大小配置,如图所示:
9)基于Docker客户端指令启动Docker容器,并且查看最新容器的磁盘空间为10G,则设置容器大小成功,如图所示:
- 高并发响应性能非常好,官方Nginx处理静态文件并发5w/s
- 反向代理性能非常好。(可用于负载均衡)
- 内存和cpu占用率低。(为Apache的1/5-1/10)
- 功能较Apache少(常用功能均有)
- 对php可使用cgi方式和fastcgi方式。
首先需要安装pcre库,然后再安装Nginx:
#安装pcre支持rewrite库,也可以安装源码,注*安装源码时,指定pcre路径为解压
源码的路径,而不是编译后的路径,否则会报错
(make[1]: *** [/usr/local/pcre/Makefile] Error 127 错误)
yum install pcre-devel pcre -y
#下载Nginx源码包
cd /usr/src ;wget -c http://nginx.org/download/nginx-1.4.2.tar.gz
#解压Nginx源码包
tar -xzf nginx-1.4.2.tar.gz
#进入解压目录,然后sed修改Nginx版本信息为WS
cd nginx-1.4.2 ; sed -i -e 's/1.4.2//g' -e 's/nginx\//WS/g' -e
's/"NGINX"/"WS"/g' src/core/nginx.h
#预编译Nginx
useradd www ;./configure --user=www --group=www --prefix=/usr/local/nginx --with-
http_stub_status_module --with-http_ssl_module
#.configure预编译成功后,执行make命令进行编译
make
#make执行成功后,执行make install 正式安装
make install
#自此Nginx安装完毕
/usr/local/nginx/sbin/nginx -t 检查nginx配置文件是否正确,返回OK即正确。
[root@localhost ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@localhost ~]#
然后启动nginx,/usr/local/nginx/sbin/nginx 回车即可。查看进程是否已启动:
[root@localhost ~]# ps -ef |grep nginx
nobody 5381 30285 0 May16 ? 00:04:31 nginx: worker process
root 30285 1 0 2014 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
root 32260 32220 0 12:34 pts/0 00:00:00 grep nginx
[root@localhost ~]#
然后我们可以通过docker 的ip去访问即可。
以上的操作是在docker上启动了一个centos7的系统不是应用,还有一种可以直接在docker官网下载Nginx镜像直接启动然后修改配置文件即可。
YUM 安装LAMP方式:
yum install httpd httpd-tools mysql mysql-server mysql-devel php php-devel php-mysql -y
源码安装LNAMP之Nginx
yum install prce-devel -y ;cd /usr/src ;wget http://nginx.org/download/nginx-1.6.0.tar.gz ;cd nginx-1.6.0 ;./configure -prefix=/usr/local/nginx && make &&make install
源码安装LNAMP之Apache
yum install apr-devel apr-util-devel –y;
cd /usr/src ; wget http://mirror.bit.edu.cn/apache/httpd/httpd-2.2.27.tar.gz ;tar xzf httpd-2.2.27.tar.gz ;cd httpd-2.2.27 ;./configure --prefix=/usr/local/apache --enable-so --enable-rewrite &&make &&make install
源码安装LNAMP之MySQL
cd /usr/src ;wget http://downloads.mysql.com/archives/mysql-5.1/mysql-5.1.63.tar.gz ;tar xzf mysql-5.1.63.tar.gz ;cd mysql-5.1.63 ;./configure --prefix=/usr/local/mysql --enable-assembler &&make &&make install
配置Mysql服务为系统服务:
cp /usr/local/mysql/share/mysql/my-medium.cnf /etc/my.cnf
cp /usr/local/mysql/share/mysql/mysql.server /etc/rc.d/init.d/mysqld
chkconfig --add mysqld
chkconfig --level 345 mysqld on
cd /usr/local/mysql
useradd mysql
chown -R mysql.mysql /usr/local/mysql
/usr/local/mysql/bin/mysql_install_db --user=mysql
chown -R mysql var
/usr/local/mysql/bin/mysqld_safe --user=mysql &
源码安装LNAMP之PHP
cd /usr/src ;wget http://mirrors.sohu.com/php/php-5.3.28.tar.bz2 ;tar jxf php-5.3.28.tar.bz2 ;cd php-5.3.28 ;./configure --prefix=/usr/local/php5 --with-config-file-path=/usr/local/php/etc --with-apxs2=/usr/local/apache/bin/apxs --with-mysql=/usr/local/mysql/
整合apache+php环境,修改httpd.conf配置文件,然后加入如下语句:
LoadModule php5_module modules/libphp5.so (默认已存在)
AddType application/x-httpd-php .php
DirectoryIndex index.php index.html (把index.php加入index.html之前)
然后在/usr/local/apache/htdocs目录下创建index.php测试页面,执行如下命令:
cat >>/usr/local/apache/htdocs/index.php <<EOF
EOF
重新启动apache服务,通过IP访问界面如下图,即代表LAMP环境搭建成功。
下载discuz源码包文件,然后解压:
cd /usr/src ;wget http://download.comsenz.com/DiscuzX/3.1/Discuz_X3.1_SC_UTF8.zip
解压discuz程序包:unzip Discuz_X3.1_SC_UTF8.zip -d /usr/local/apache/htdocs/
重命名程序文件:cd /usr/local/apache/htdocs/ ;mv upload/* .
赋予discuz目录完全访问权限:cd /usr/local/apache/htdocs/ ;chmod 777 -R data/ uc_server/ config/ uc_client/
create database discuz charset=utf8;
grant all on discuz.* to root@'localhost' identified by "123456";
#!/bin/bash
#auto install docker and Create VM
#by wugk 2021-10-22
#Define PATH Varablies
IPADDR=`ifconfig |grep "Bcast"|awk '{print $2}'|cut -d: -f2|grep "192.168"|head -1`
GATEWAY=`route -n|grep "UG"|awk '{print $2}'|grep "192.168"|head -1`
DOCKER_IPADDR=$1
IPADDR_NET=`ifconfig |grep "Bcast"|awk '{print $2}'|cut -d: -f2|grep "192.168"|head -1|awk -F. '{print $1"."$2"."$3".""xxx"}'`
NETWORK=(
HWADDR=`ifconfig eth0 |egrep "HWaddr|Bcast" |tr "\n" " "|awk '{print $5,$7,$NF}'|sed -e 's/addr://g' -e 's/Mask://g'|awk '{print $1}'`
IPADDR=`ifconfig eth0 |egrep "HWaddr|Bcast" |tr "\n" " "|awk '{print $5,$7,$NF}'|sed -e 's/addr://g' -e 's/Mask://g'|awk '{print $2}'`
NETMASK=`ifconfig eth0 |egrep "HWaddr|Bcast" |tr "\n" " "|awk '{print $5,$7,$NF}'|sed -e 's/addr://g' -e 's/Mask://g'|awk '{print $3}'`
GATEWAY=`route -n|grep "UG"|awk '{print $2}'`
)
if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$4" ];then
echo -e "\033[32m---------------------------------\033[0m"
echo -e "\033[32mPlease exec $0 IPADDR CPU(C) MEM(G) DISK(G),example $0 $IPADDR_NET 16 32 50\033[0m"
exit 0
fi
CPU=`expr $2 - 1`
if [ ! -e /usr/bin/bc ];then
yum install bc -y >>/dev/null 2>&1
fi
MEM_F=`echo $3 \* 1024|bc`
MEM=`printf "%.0f\n" $MEM_F`
DISK=$4
USER=$5
REMARK=$6
ping $DOCKER_IPADDR -c 1 >>/dev/null 2>&1
if [ $? -eq 0 ];then
echo -e "\033[32m---------------------------------\033[0m"
echo -e "\033[32mThe IP address to be used,Please change other IP,exit.\033[0m"
exit 0
fi
if [ ! -e /etc/init.d/docker ];then
rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
yum install docker-io -y
yum install device-mapper* -y
/etc/init.d/docker start
if [ $? -ne 0 ];then
echo "Docker install error ,please check."
exit
fi
fi
cd /etc/sysconfig/network-scripts/
mkdir -p /data/backup/`date +%Y%m%d-%H%M`
yes|cp ifcfg-eth* /data/backup/`date +%Y%m%d-%H%M`/
if
[ -e /etc/sysconfig/network-scripts/ifcfg-br0 ];then
echo
else
cat >ifcfg-eth0 <<EOF
DEVICE=eth0
BOOTPROTO=none
${NETWORK[0]}
NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
BRIDGE="br0"
${NETWORK[1]}
${NETWORK[2]}
${NETWORK[3]}
USERCTL=no
EOF
cat >ifcfg-br0 <<EOF
DEVICE="br0"
BOOTPROTO=none
${NETWORK[0]}
IPV6INIT=no
NM_CONTROLLED=no
ONBOOT=yes
TYPE="Bridge"
${NETWORK[1]}
${NETWORK[2]}
${NETWORK[3]}
USERCTL=no
EOF
/etc/init.d/network restart
fi
echo 'Your can restart Ethernet Service: /etc/init.d/network restart !'
echo '---------------------------------------------------------'
cd -
#######create docker container
service docker status >>/dev/null
if [ $? -ne 0 ];then
/etc/init.d/docker restart
fi
NAME="Docker$$_`echo $DOCKER_IPADDR|awk -F"." '{print $(NF-1)"_"$NF}'`"
IMAGES=`docker images|grep -v "REPOSITORY"|grep -v "none"|head -1|awk '{print $1}'`
CID=$(docker run -itd --cpuset-cpus=0-$CPU -m ${MEM}m --net=none --name=$NAME $IMAGES /bin/bash)
if [ -z $IMAGES ];then
echo "Plesae Download Docker Centos Images,you can to be use docker search centos,and docker pull centos6.5-ssh,exit 0"
exit 0
fi
if [ ! -f /usr/local/bin/pipework ];then
yum install wget unzip zip -y
wget https://github.com/jpetazzo/pipework/archive/master.zip
unzip master
cp pipework-master/pipework /usr/local/bin/
chmod +x /usr/local/bin/pipework
rm -rf master
fi
ip netns >>/dev/null
if [ $? -ne 0 ];then
rpm -e iproute --nodeps
rpm -ivh https://repos.fedorapeople.org/openstack/EOL/openstack-grizzly/epel-6/iproute-2.6.32-130.el6ost.netns.2.x86_64.rpm
fi
pipework br0 $NAME $DOCKER_IPADDR/24@$IPADDR
docker ps -a |grep "$NAME"
DEV=$(basename $(echo /dev/mapper/docker-*-$CID))
dmsetup table $DEV | sed "s/0 [0-9]* thin/0 $((${DISK}*1024*1024*1024/512)) thin/" | dmsetup load $DEV
dmsetup resume $DEV
resize2fs /dev/mapper/$DEV
docker start $CID
docker logs $CID
LIST="docker_vmlist.csv"
if [ ! -e $LIST ];then
echo "编号,容器ID,容器名称,CPU,内存,硬盘,容器IP,宿主机IP,使用人,备注" >$LIST
fi
###################
NUM=`cat docker_vmlist.csv |grep -v CPU|tail -1|awk -F, '{print $1}'`
if [[ $NUM -eq "" ]];then
NUM="1"
else
NUM=`expr $NUM + 1`
fi
##################
echo -e "\033[32mCreate virtual client Successfully.\n$NUM `echo $CID|cut -b 1-12` $NAME $2C ${MEM}M ${DISK}G $DOCKER_IPADDR $IPADDR $USER $REMARK\033[0m"
if [ -z $USER ];then
USER="NULL"
REMARK="NULL"
fi
echo $NUM,`echo $CID|cut -b 1-12`,$NAME,${2}C,${MEM}M,${DISK}G,$DOCKER_IPADDR,$IPADDR,$USER,$REMARK >>$LIST
rm -rf docker_vmlist_*
iconv -c -f utf-8 -t gb2312 docker_vmlist.csv -o docker_vmlist_`date +%H%M`.csv
#!/bin/bash
#auto install docker and Create VM
#by jfedu.net 2017
#Define PATH Varablies
IPADDR=`ifconfig|grep -E "\" |awk '{print $2}'|grep "192.168"|head -1`
GATEWAY=`route -n|grep "UG"|awk '{print $2}'|grep "192.168"|head -1`
IPADDR_NET=`ifconfig|grep -E "\" |awk '{print $2}'|grep "192.168"|head -1|awk -F. '{print $1"."$2"."$3"."}'`
LIST="/root/docker_vmlist.csv"
if [ ! -f /usr/sbin/ifconfig ];then
yum install net-tools* -y
fi
for i in `seq 1 253`;do ping -c 1 ${IPADDR_NET}${i} ;[ $? -ne 0 ]&& DOCKER_IPADDR="${IPADDR_NET}${i}" &&break;done >>/dev/null 2>&1
echo "##################"
echo -e "Dynamic get docker IP,The Docker IP address\n\n$DOCKER_IPADDR"
NETWORK=(
HWADDR=`ifconfig eth0|grep ether|awk '{print $2}'`
IPADDR=`ifconfig eth0|grep -E "\" |awk '{print $2}'`
NETMASK=`ifconfig eth0|grep -E "\" |awk '{print $4}'`
GATEWAY=`route -n|grep "UG"|awk '{print $2}'`
)
if [ -z "$1" -o -z "$2" ];then
echo -e "\033[32m---------------------------------\033[0m"
echo -e "\033[32mPlease exec $0 CPU(C) MEM(G),example $0 4 8\033[0m"
exit 0
fi
#CPU=`expr $2 - 1`
if [ ! -e /usr/bin/bc ];then
yum install bc -y >>/dev/null 2>&1
fi
CPU_ALL=`cat /proc/cpuinfo |grep processor|wc -l`
if [ ! -f $LIST ];then
CPU_COUNT=$1
CPU_1="0"
CPU1=`expr $CPU_1 + 0`
CPU2=`expr $CPU1 + $CPU_COUNT - 1`
if [ $CPU2 -gt $CPU_ALL ];then
echo -e "\033[32mThe System CPU count is $CPU_ALL,not more than it.\033[0m"
exit
fi
else
CPU_COUNT=$1
CPU_1=`cat $LIST|tail -1|awk -F"," '{print $4}'|awk -F"-" '{print $2}'`
CPU1=`expr $CPU_1 + 1`
CPU2=`expr $CPU1 + $CPU_COUNT - 1`
if [ $CPU2 -gt $CPU_ALL ];then
echo -e "\033[32mThe System CPU count is $CPU_ALL,not more than it.\033[0m"
exit
fi
fi
MEM_F=`echo $2 \* 1024|bc`
MEM=`printf "%.0f\n" $MEM_F`
DISK=20
USER=$3
REMARK=$4
ping $DOCKER_IPADDR -c 1 >>/dev/null 2>&1
if [ $? -eq 0 ];then
echo -e "\033[32m---------------------------------\033[0m"
echo -e "\033[32mThe IP address to be used,Please change other IP,exit.\033[0m"
exit 0
fi
if [ ! -e /usr/bin/docker ];then
yum install docker* device-mapper* lxc -y
mkdir -p /export/docker/
cd /var/lib/ ;rm -rf docker ;ln -s /export/docker/ .
mkdir -p /var/lib/docker/devicemapper/devicemapper
dd if=/dev/zero of=/var/lib/docker/devicemapper/devicemapper/data bs=1G count=0 seek=2000
service docker start
if [ $? -ne 0 ];then
echo "Docker install error ,please check."
exit
fi
fi
cd /etc/sysconfig/network-scripts/
mkdir -p /data/backup/`date +%Y%m%d-%H%M`
yes|cp ifcfg-eth* /data/backup/`date +%Y%m%d-%H%M`/
if
[ -e /etc/sysconfig/network-scripts/ifcfg-br0 ];then
echo
else
cat >ifcfg-eth0<<EOF
DEVICE=eth0
BOOTPROTO=none
${NETWORK[0]}
NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
BRIDGE="br0"
${NETWORK[1]}
${NETWORK[2]}
${NETWORK[3]}
USERCTL=no
EOF
cat >ifcfg-br0 <<EOF
DEVICE="br0"
BOOTPROTO=none
${NETWORK[0]}
IPV6INIT=no
NM_CONTROLLED=no
ONBOOT=yes
TYPE="Bridge"
${NETWORK[1]}
${NETWORK[2]}
${NETWORK[3]}
USERCTL=no
EOF
/etc/init.d/network restart
fi
echo 'Your can restart Ethernet Service: /etc/init.d/network restart !'
echo '---------------------------------------------------------'
cd -
#######create docker container
service docker status >>/dev/null
if [ $? -ne 0 ];then
service docker restart
fi
NAME="Docker_`echo $DOCKER_IPADDR|awk -F"." '{print $(NF-1)"_"$NF}'`"
IMAGES=`docker images|grep -v "REPOSITORY"|grep -v "none"|grep "centos"|head -1|awk '{print $1}'`
if [ -z $IMAGES ];then
echo "Plesae Download Docker Centos Images,you can to be use docker search centos,and docker pull centos6.5-ssh,exit 0"
if [ ! -f jfedu_centos68.tar ];then
echo "Please upload jfedu_centos68.tar for docker server."
exit
fi
cat jfedu_centos68.tar|docker import - jfedu_centos6.8
fi
IMAGES=`docker images|grep -v "REPOSITORY"|grep -v "none"|grep "centos"|head -1|awk '{print $1}'`
CID=$(docker run -itd --privileged --cpuset-cpus=${CPU1}-${CPU2} -m ${MEM}m --net=none --name=$NAME $IMAGES /bin/bash)
echo $CID
docker ps -a |grep "$NAME"
pipework br0 $NAME $DOCKER_IPADDR/24@$IPADDR
docker exec $NAME /etc/init.d/sshd start
if [ ! -e $LIST ];then
echo "编号,容器ID,容器名称,CPU,内存,硬盘,容器IP,宿主机IP,使用人,备注" >$LIST
fi
###################
NUM=`cat $LIST |grep -v CPU|tail -1|awk -F, '{print $1}'`
if [[ $NUM -eq "" ]];then
NUM="1"
else
NUM=`expr $NUM + 1`
fi
##################
echo -e "\033[32mCreate virtual client Successfully.\n$NUM `echo $CID|cut -b 1-12`,$NAME,$CPU1-$CPU2,${MEM}M,${DISK}G,$DOCKER_IPADDR,$IPADDR,$USER,$REMARK\033[0m"
if [ -z $USER ];then
USER="NULL"
REMARK="NULL"
fi
echo $NUM,`echo $CID|cut -b 1-12`,$NAME,$CPU1-$CPU2,${MEM}M,${DISK}G,$DOCKER_IPADDR,$IPADDR,$USER,$REMARK >>$LIST
rm -rf /root/docker_vmlist_*
iconv -c -f utf-8 -t gb2312 $LIST -o /root/docker_vmlist_`date +%H%M`.csv