Docker是一个开源的应用容器引擎,使用Go语言开发,基于Linux内核的cgroup, namespace, Union FS等技术,对应用进程进行封装隔离,而且独立于宿主机与其余进程,这种运行时封装的状态称为容器。Docker早起版本实现是基于LXC,并进一步对其封装,包括文件系统、网络互联、镜像管理等方面,极大简化了容器管理。从0.7版本之后开始去除LXC,转为自行研发的libcontainer,从1.11版本开始,进一步演进为使用runC和containerd。
Docker理念是将应用及依赖包打包到一个可移植的容器中,可发布到任意Linux发行版Docker引擎上。使用沙箱机制运行程序,程序之间相互隔离。html
Containerd:是一个简单的守护进程,使用runC管理容器。向Docker Engine提供接口。
Shim:只负责管理一个容器。
runC:是一个轻量级的工具, 只用来运行容器。java
Namespaces
命名空间, Linux内核提供的一种对进程资源隔离的机制,例如进程、网络、挂载点等资源。
CGroupsnode
控制组, Linux内核提供的一种限制进程资源的机制; 例如CPU、内存等资源。
UnionFS
联合文件系统,支持将不一样位置的目录挂载到同一虚拟文件系统, 造成一种分层的模型。mysql
虚拟机与容器的区别linux
以KVM举例,与Docker对比nginx
启动时间
Docker秒级启动, KVM分钟级启动。git
轻量级
容器镜像大小一般以M为单位,虚拟机以G为单位。
容器资源占用小,要比虚拟机部署更快速。github
性能
容器共享宿主机内核,系统级虚拟化,占用资源少,没有Hypervisor层开销,容器性能基本接近物理机;
虚拟机须要Hypervisor层支持,虚拟化一些设备,具备完整的GuestOS,虚拟化开销大,于是下降性能,没有容器性能好。web
安全性
因为共享宿主机内核,只是进程级隔离,所以隔离性和稳定性不如虚拟机,容器具备必定权限访问宿主机内核,存在必定安全隐患。redis
使用要求
KVM基于硬件的彻底虚拟化,须要硬件CPU虚拟化技术支持;
容器共享宿主机内核,可运行在主流的Linux发行版,不用考虑CPU是否支持虚拟化技术。
应用场景
场景一: 节省项目环境部署时间
1. 单项目打包
2. 整套项目打包
3. 新开源技术试用
场景二: 环境一致性
场景三: 持续集成
场景四: 微服务
场景五: 弹性伸缩
Linux 环境下docker的安装
基于centos7的环境下
# 安装依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加软件源信息 源地址换成阿里
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新yum包索引
yum makecache fast
# 安装Docker CE
yum install docker-ce
# 启动
systemctl start docker
# 卸载
yum remove docker-ce
rm -rf /var/lib/docker
#卸载centos自带的firewall
systemctl stop firewalld.service #关闭防火墙
systemctl disable firewalld.service #关闭开机启动
#下载iptables
yum install iptables (根据centOS7的版本和内核,有些版本已经装过,能够跳过此命令)
yum install iptables-services
service iptables restart
chkconfig iptables on或者
systemctl enable iptables.service #开机自启
镜像与配置国内镜像仓库
简单说, Docker镜像是一个不包含Linux内核而又精简的Linux操做系统
Docker Hub是由Docker公司负责维护的公共注册中心,包含大量的容器镜像, Docker工具
默认从这个公共镜像库下载镜像
https://hub.docker.com/explore
默认是国外的源,下载会慢,建议配置国内镜像仓库:
# vim /etc/docker/daemon.json
{
"registry-mirrors": [ "https://registry.docker-cn.com"]
}
镜像与容器的关系
镜像不是一个单一的文件,而是有多层构成。 咱们能够经过docker history <ID/NAME> 查看镜像中各层内容及大小,每层对应着Dockerfile中的一条指令。 Docker镜像默认存储在/var/lib/docker/<storage-driver>中。
容器实际上是在镜像的最上面加了一层读写层,在运行容器里作的任何文件改动, 都会写到这个读写层。 若是容器删除了,最上面的读写层也就删除了,改动也就丢失了。Docker使用存储驱动管理镜像每层内容及可读写层的容器层。
容器管理指令
指令 |
描述 |
ls |
列出镜像 |
build |
建立 |
inspect |
显示一个或多个镜像详细信息 |
pull |
从镜像仓库拉取镜像 |
push |
推送一个镜像到镜像仓库 |
rm |
移除一个或多个镜像 |
prune |
移除未使用的镜像,没有被标记或被任何容器引用的 |
tag |
建立一个引用源镜像标记目标镜像 |
export |
导出容器文件系统到tar归档文件 |
import |
导入容器文件系统tar归档温江建立镜像 |
save |
保存一个或多个镜像到一个tar归档文件 |
load |
加载镜像来自tar归档或标准输入 |
#docker 导出一个镜像
docker save nginx:1.11 > nginx1.11.tar
#docker 导入一个镜像
docker load < nginx1.11.tar
#docker 导出一个容器
docker export 82df6c127b53 > nginx_start.tar
#docker 导入一个容器
docker import nginx_start.tar
#命名一个名字 和标记
docker import nginx_start.tar nginx:self
#建立容器,并命名
docker run -itd --name web_1 nginx:1.11
#这个容器打开一个新的窗口
docker container exec -it web_1 bash
#带一个变量到容器中
docker container run -itd -e a=123 --name web_2 nginx:1.11
#内存&cpu使用率
docker container stats web_2
指令 |
描述 |
-t, --interactive |
交互式 |
-t, --tty |
分配一个伪终端 |
-a, --attach list |
附加到运行的容器 |
--dns list |
设置dns服务器 |
-e --env list |
设置环境变量 |
--env-file list |
从文件读取环境变量 |
-p, --publish list |
发布容器端口到宿主机 |
-P, --publish-all |
发布容器的全部EXPOSE的端口到宿主机随机端口 |
-h, --hostname string |
设置容器主机名 |
--ip string |
指定容器ip, 只能用于自定义网络 |
--link string |
添加链接到另外一个容器 |
--network |
链接容器到一个网络 |
--mount month |
挂载宿主机分区到容器 |
-v, --volume list |
挂载宿主机目录到容器 |
--restart string |
容器退出时重启策略,默认no[always|on-failure] |
--add-host list |
添加其余主机到容器中 /etc/hosts |
资源限制指令 |
描述 |
-m, --memory |
容器能够使用的最大内存量 |
--memory-swap |
容许交换到磁盘的内存量 |
--cpus |
限制容器能够使用多少可用的cpu资源 |
--cpuset-cpus |
限制容器能够使用的特定的cpu |
容器管理经常使用命令
指令 |
描述 |
ls |
列出容器 |
inspect |
显示一个或多个容器详细信息 |
attach |
附加本地标准输入,输出和错误到一个运行的容器 |
exec |
再运行容器中执行命令 |
commit |
建立一个新镜像来自一个容器 |
cp |
拷贝文件/文件夹到一个容器 |
logs |
获取一个容器日志 |
port |
列出一个容器日志 |
stats |
显示容器资源使用统计 |
top |
显示一个容器运行的进程 |
update |
更新一个或多个容器 |
stop/start |
中止/启动一个或多个容器 |
rm |
删除一个或多个容器 |
4. 管理应用程序数据
将docker主机书籍挂载到容器
Docker提供三种不一样的方式将数据从宿主机挂载到容器中:volumes, bind mounts 和tmpfs
volumes: docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)
bind mounts: 能够存储在宿主机系统的任意位置
tmpfs:挂载存储在宿主机系统的内存中,而不会写入宿主机的文件系统
Volume
管理卷:
# docker volume create nginx-vol
# docker volume ls
# docker volume inspect nginx-vol
用卷建立一个容器:
# docker run -d -it --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
# docker run -d -it --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx
清理:
# docker container stop nginx-test
# docker container rm nginx-test
# docker volume rm nginx-vol
注意:
1. 若是没有指定卷,自动建立。
2. 建议使用—mount,更通用
Bind Mounts
用卷建立一个容器:
#docker run -d -it --name=nginx-test --mount type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx
# docker run -d -it --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html nginx
验证绑定:
# docker inspect nginx-test
清理:
# docker container stop nginx-test
# docker container rm nginx-test
注意:
1. 若是源文件/目录没有存在,不会自动建立,会抛出一个错误。
2. 若是挂载目标在容器中非空目录,则该目录现有内容将被隐藏。
Dockerfile指令
指令 |
描述 |
指令 |
描述 |
FROM |
构建的镜像是基于哪一个镜像的。例如:FROM:centos:6 |
COPY |
拷贝文件或目录到镜像,用法同上 例如: COPY ./start.sh /start.sh |
MAINTAINER |
镜像的维护者 |
ENTRYPOINT |
运行容器时执行的Shell命令 例如: ENTRYPOINT [“/bin/bash", “-c", “/start.sh"] ENTRYPOINT /bin/bash -c ‘/start.sh |
RUN |
构建镜像时运行的shell命令 例如: RUN[“yum”,”install”,”httpd”] RUN yum install httpd |
VOLUME |
指定容器挂载点到宿主机自动生成的目录或其余容器 例如: VOLUME ["/var/lib/mysql"] |
CMD |
运行容器时执行的shell命令 例如: CMD[“-c”,”/start.sh”] CMD[“/usr/sbin/sshd”,”-D”] CMD /usr/sbin/sshd -D |
USER |
为RUN、 CMD和ENTRYPOINT执行命令指定运行用户 USER <user>[:<group>] or USER <UID>[:<GID>] 例如: USER augustyang |
EXPOSE |
声明容器运行的服务端口 例如:EXPOSE 90 3306 |
WORKDIR |
为RUN CMD ENTRYPOINT COPY 设置工做目录 |
ENV |
设置环境变量 例如 ENV JAVA_HOME /kitty/jdk1.7.0_80 |
HEALTHCHECK |
健康检查
|
ADD |
拷贝文件或目录到镜像,若是是URL或压缩包会自动下载或自动解压 ADD <src>… <dest> ADD [“<src>”,… “<dest>”] ADD https://xxx.com/html.tar.gz /var/www/html ADD html.tar.gz /var/www/html |
ARG |
在构建镜像时指定一些参数 例如 FROM centos:6 ARG user #ARG user=root USER $user #docker build --build-arg user=augustyang Dockerfile . |
build 构建
docker build -t nginx:v3 .
CMD与ENTRYPOINT的区别
FROM centos:6
MAINTAINER yang_yang
RUN mkdir /ysl
RUN touch /ysl/test.txt
ENTRYPOINT ["echo","ENTRYPOINT"]
CMD ["CMD"]
注:ENTRYPOINT须要放在CDM前面 。
docker run image_name 输出:ENTRYPOINT CMD
docker run image_name ysl 输出:ENTRYPOINT ysl
1)启动容器没带参数:起默认参数,
2)启动容器带参数:所带参数替换默认参数
构建java的dockerfile
FROM centos:6
MAINTAINER yang_yang
ENV JAVA_HOME /kitty/jdk1.7.0_80
ADD apache-tomcat-8.0.43.tar.gz /kitty
WORKDIR /kitty/apache-tomcat-8.0.43
EXPOSE 8080
ENTRYPOINT ["./bin/catalina.sh", "run"]
启动一个tomcat的示例
docker run -d -it \
-p 8084:8080 \
--name=kitty_notice \
--link mysql:db \
--net kitty \
--ip 172.18.0.8 \
-v /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 \
-v/data:/data \
--mount type=bind,src=/kitty/kitty_notice,dst=/kitty/apache-tomcat-8.0.43/webapps \
tomcat:v1
#安装必要的一些系统工具
yum install -y yum-utils device-mapper-persistent-data lvm2
#添加软件源信息 源地址换成阿里
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#更新并安装 Docker-CE
yum makecache fast
yum -y install docker-ce
https://github.com/vmware/harbor/releases #下载离线包(二进制)
安装docker-compose
下载docker-compose
unzip docker-compose-linux-x86_64.zip
mv docker-compose /usr/bin
chmox +x /usr/bin/docker-compose
自签TLS证书
https://github.com/vmware/harbor/blob/master/docs/configure_https.md
1) 进入harbor里面, 建立ssl 目录 # mkdir harbor/ssl && cd harbor/ssl
2) #Create your own CA certificate
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 365 -out ca.crt
3) 生成证书签名
openssl req -newkey rsa:4096 -nodes -sha256 -keyout reg.yangshanlei.com.key -out reg.yangshanlei.com.csr
4) 生成注册表主机的证书
openssl x509 -req -days 365 -in reg.yangshanlei.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out reg.yangshanlei.com.crt
Harbor安装与配置
1)修改配置文件 vim harbor.cfg
hostname = reg.yangshanlei.com
ui_url_protocol = https
ssl_cert = ./ssl/reg.yangshanlei.com.crt
ssl_cert_key = ./ssl/reg.yangshanlei.com.key
harbor_admin_password = 12345
2) ./prepare
3) ./install.sh
4) docker-compose ps
Docker主机访问Harbor
客户端
hosts配置文件修改 192.168.2.84 reg.yangshanlei.com
mkdir -p /etc/docker/certs.d/reg.yangshanlei.com/
scp root@192.168.2.84:/root/harbor/ssl/reg.yangshanlei.com.crt /etc/docker/certs.d/reg.yangshanlei.com/
docker login reg.yangshanlei.com -u test -p Yangshanlei@2018 #私有仓库须要登陆才能下载和上传, 公开仓库没有上传的权限
Portainer
Portainer是一个开源、轻量级Docker管理用户界面,基于Docker API,可管理Docker主机或Swarm集群,支持最新版Docker和Swarm模式
一、建立卷
# docker volume create portainer_data
二、建立Portainer容器
# docker run -d \
-p 9000:9000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer
cAdvisor+InfluxDB+Grafana
Influxdb #数据库
docker run -d \
--name influxdb \
--net monitor \
-p 7083:8083 \
-p 7086:8086 \
tutum/influxdb
cAdvisor
docker run -d \
--name=cadvisor \
--net monitor \
-p 7081:8080 \
--mount type=bind,src=/,dst=/rootfs,ro \
--mount type=bind,src=/var/run,dst=/var/run \
--mount type=bind,src=/sys,dst=/sys,ro \
--mount type=bind,src=/var/lib/docker/,dst=/var/lib/docker,ro \
google/cadvisor \
-storage_driver=influxdb \
-storage_driver_db=cadvisor \
-storage_driver_host=influxdb:8086
Grafana
docker run -d \
--name grafana \
--net monitor \
-p 3000:3000 \
grafana/grafana
mongdb docker-compose
version: '3' services: mongo: image: mongo:3.4 restart: always ports: - 27017:27017 - 28017:28017 environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: 123456 TZ: Asia/Shanghai volumes: - /data/db:/data/db
项目软件和程序放在一块儿(一个游戏项目)
tomcat Dockerfile +apache-tomcat-8.0.43.tar.gz
FROM centos:6 MAINTAINER yang_yang ENV JAVA_HOME /kitty/jdk1.7.0_80 ADD apache-tomcat-8.0.43.tar.gz /kitty RUN sed -i '1a JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"' /kitty/apache-tomcat-8.0.43/bin/catalina.sh\ && /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone WORKDIR /kitty/apache-tomcat-8.0.43 EXPOSE 8080 ENTRYPOINT ["./bin/catalina.sh", "run"]
redis Dockerfile + redis-3.2.5.tar.gz
FROM centos:6 ADD redis-3.2.5.tar.gz /opt/ RUN yum -y install gcc net-tools make zip unzip RUN cd /opt/redis-3.2.5/src/ && make && make install\ && cd /opt/redis-3.2.5/utils/ && echo | /bin/bash install_server.sh\ && sed -i 's/bind 127.0.0.1/bind 0.0.0.0/g' /etc/redis/6379.conf\ && sed -i 's/# requirepass foobared/requirepass 123456/g' /etc/redis/6379.conf\ && /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone EXPOSE 6379 ENTRYPOINT /usr/local/bin/redis-server /etc/redis/6379.conf && tail -f -n20 /var/log/redis_6379.log
mysql 建立2个目录:conf (存放my.cnf) data (数据持久化)
[mysqld] user=mysql port=3306 datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock pid-file=/var/run/mysql/mysql.pid log_error=/var/log/mysql/error.log character_set_server = utf8 max_connections=3600
game Dockerfile
FROM centos:6 MAINTAINER yang_yang ENV JAVA_HOME /kitty/jdk1.7.0_80 RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone EXPOSE 3301 EXPOSE 23301 EXPOSE 1234 WORKDIR /kitty/kitty_game/bin ENTRYPOINT bash /kitty/kitty_game/bin/game.sh start && tail -f /dev/null
friend Dockerfile
FROM centos:6 MAINTAINER yang_yang ENV JAVA_HOME /kitty/jdk1.7.0_80 RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone EXPOSE 43301 WORKDIR /kitty/kitty_friend/bin ENTRYPOINT bash /kitty/kitty_friend/bin/game.sh start && tail -f /dev/null
docker-compose
version: '3' services: zk1: image: zookeeper restart: always hostname: zk1 ports: - 2181:2181 networks: - kitty environment: ZOO_MY_ID: 1 ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zk2:2888:3888 server.3=zk3:2888:3888 TZ: Asia/Shanghai zk2: image: zookeeper restart: always hostname: zk2 ports: - 2182:2181 networks: - kitty environment: ZOO_MY_ID: 2 ZOO_SERVERS: server.1=zk1:2888:3888 server.2=0.0.0.0:2888:3888 server.3=zk3:2888:3888 TZ: Asia/Shanghai zk3: image: zookeeper restart: always hostname: zk3 ports: - 2183:2181 networks: - kitty environment: ZOO_MY_ID: 3 ZOO_SERVERS: server.1=zk1:2888:3888 server.2=zk3:2888:3888 server.3=0.0.0.0:2888:3888 TZ: Asia/Shanghai kafka1: image: wurstmeister/kafka hostname: kafka1 restart: always ports: - 9092:9092 networks: - kitty environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zk2:2181,zk1:2181,zk3:2181 KAFKA_ADVERTISED_HOST_NAME: kafka1 KAFKA_ADVERTISED_PORT: 9092 TZ: Asia/Shanghai kafka2: image: wurstmeister/kafka hostname: kafka2 restart: always ports: - 9093:9092 networks: - kitty environment: KAFKA_BROKER_ID: 2 KAFKA_ZOOKEEPER_CONNECT: zk2:2181,zk1:2181,zk3:2181 KAFKA_ADVERTISED_HOST_NAME: kafka2 KAFKA_ADVERTISED_PORT: 9092 TZ: Asia/Shanghai kafka3: image: wurstmeister/kafka hostname: kafka3 restart: always ports: - 9094:9092 networks: - kitty environment: KAFKA_BROKER_ID: 3 KAFKA_ZOOKEEPER_CONNECT: zk2:2181,zk1:2181,zk3:2181 KAFKA_ADVERTISED_HOST_NAME: kafka3 KAFKA_ADVERTISED_PORT: 9092 TZ: Asia/Shanghai kitty_mysql: hostname: kitty_mysql image: mysql:5.6 ports: - 3306:3306 networks: - kitty volumes: - ./mysql/conf:/etc/mysql/conf.d - ./mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_USER: kitty MYSQL_PASSWORD: kitty TZ: Asia/Shanghai kitty_redis: hostname: kitty_redis build: context: ./redis dockerfile: Dockerfile ports: - 6379:6379 networks: - kitty kitty_auth: hostname: kitty_auth build: context: ./tomcat dockerfile: Dockerfile ports: - 8081:8080 networks: - kitty volumes: - /kitty/kitty_auth:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_activity: hostname: kitty_activity build: context: ./tomcat dockerfile: Dockerfile ports: - 8082:8080 networks: - kitty volumes: - /kitty/kitty_activity:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_gm: hostname: kitty_gm build: context: ./tomcat dockerfile: Dockerfile ports: - 8083:8080 networks: - kitty volumes: - /kitty/kitty_gm:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_idip: hostname: kitty_idip build: context: ./tomcat dockerfile: Dockerfile ports: - 8084:8080 networks: - kitty volumes: - /kitty/kitty_idip:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_notice: hostname: kitty_notice build: context: ./tomcat dockerfile: Dockerfile ports: - 8085:8080 networks: - kitty volumes: - /kitty/kitty_notice:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_game: hostname: kitty_game restart: always build: ./game ports: - 3301:3301 networks: - kitty volumes: - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /kitty/kitty_game:/kitty/kitty_game - /data:/data kitty_friend: hostname: kitty_friend restart: always build: ./friend ports: - 43301:43301 networks: - kitty volumes: - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /kitty/kitty_friend:/kitty/kitty_friend - /data:/data networks: kitty:
ps: 全部的软件和程序都放在一块儿, 每次启停都把依赖的软件都重启了,不推荐
程序和软件分离 建立2个docker-compose: 须要注意的的是每一个软件不须要指定网络例如.只在最后指定下网络,这样2个docker-compose 就能够网络互连, kitty这个网络须要事先先建立