Docker学习笔记
Docker主要功能
项目打包时带上环境,一次打包,到处运行
Docker核心思想
- 容器间相互隔离
- 将服务器资源利用到极致
Docker优点
-
开源
-
在docker之前,vm技术占主流,但是很笨重,麻烦。
-
虚拟机是虚拟化技术的一种实现方式,docker也是一种虚拟化技术的实现方式。
-
docker很轻巧
-
docker秒级启动
Docker基本介绍
- 基于Go开发
- 官网:https://www.docker.com/
- 文档地址:https://docs.docker.com/
- 仓库地址:https://hub.docker.com/
容器化技术和传统虚拟机区别
- 容器化技术不是模拟一个完整的操作系统
- 传统的虚拟机,是虚拟出一套硬件,在上面运行完整的操作系统
- 容器内的应用是直接运行在宿主机上,容器自己没有内核,也不需要去虚拟硬件,所以很轻
- 每个容器间都是相互隔离,每个容器都有属于自己的文件系统,互不影响
DevOps (开发、运维)
应用更快速的交付和部署
传统:一堆的帮助文档,安装程序
Docker:打包镜像发布测试,一键运行
更便捷的升级和扩缩容
更简单的系统运维
更高效的计算资源利用
Docker是内核级别的虚拟化
容器命令
docker run [参数] image
--name 容器名
-it 交互进入
-p ip:主机端口:容器端口
-p 主机端口:容器端口
-p 容器端口
-P 随机端口
docker ps [参数]
docker ps -n=2 # 最近2个容器
docker rm -f $(docker ps -aq)
docker ps -aq|xargs docker rm -f
其他常用命令
docker run -d image
对于centos镜像如果此时没有前台程序,那么启动时候会立即停止
可以用
-dit
来启动
docker logs -f -t --tail 10 ID #输出10行日志
docker top ID #容器内部进程信息
docker inspect ID #查看容器元数据信息
docker exec -it ID /bin/bash #进入容器 开启新的终端 会启
动新的进程
docker attach 进入容器 不会开启新终端 若从这里exit 会终止容器 若想不终止 要用ctrl + q + p
docker cp 容器id:容器路径 主机路径 #复制 可以互相复制
docker run -it --rm image # 启动后就删掉容器 用于测试
docker history + image:tag # 查看镜像的创建过程
Docker可视化
-
portainer(练习用)
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer、portainer
-
Rancher(CI/CD时候用)
Docker镜像讲解
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和相关软件、配置等。
获取镜像
- 远程仓库
- 外部拷贝
- 自己制作
镜像加载原理
unionFS(联合文件系统)
分层文件系统
Docker镜像原理
一层一层加载
容器启动的时候,一个新的可写层被加载到镜像的顶部,这一层通常称为容器层,可以通过commit命令,重新生成一个镜像。
commit镜像
docker commit 将容器提交为一个新的镜像
docker commit -m="提交的信息" -a="作者" 容器id 目标镜像名:[TAG]
容器数据卷
容器间数据共享的技术
将容器内的目录挂载到宿主机 上
总结一句话:容器的持久化和同步操作!容器间也可以数据共享!
docker run -v 主机目录:容器内目录
具名和匿名挂载
-
匿名挂载
docker -v 容器内目录 docker volume ls
-
具名挂载
docker -v name:容器内目录 #不写路径的只有卷名 docker volume ls docker volume inspect nginxme
匿名的的挂在卷放在 /var/lib/docker/volumes/
-
指定路径挂载
-
docker -v /home/nginx:容器内目录 docker volume ls
数据卷容器
docker run -it --name dc02 --volumes-from dc01 xx/centos
docker run -it --name dc03 --volumes-from dc01 xx/centos
dc02容器和dc03容器继承自dc01 容器 文件是双向拷贝的 dc01 删了后 dc02、dc03文件还在
DockerFile
构建docker镜像的构建文件
基础知识
- 每个关键字都是大写
- 执行是从上到下执行
#
表示注释- 每一个指令都会创建一个新的镜像层
指令
FROM
MAINTAINER # 镜像作者+邮箱
RUN # 构建时需运行的命令
AND # 添加 可以将添加进来的tar包解压
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定容器启动时运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定容器启动时运行的命令,可以追加命令
ONBUILD # 当构建一个被继承的镜像 会触发
COPY # 类似ADD 拷贝文件到镜像中
ENV # 构建时设置环境变量
示例一
FROM centos
MAINTAINER peterven<peterven@126.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 8087
CMD echo $MYPATH
CMD echo "-----end----"
CMD /bin/bash
CMD 和 ENTRYPOINT区别
FROM centos
CMD [“ls”, “-a”]
# ENTRYPOINT ["ls", "-a"]
CMD特点
-
只有最后一个CMD会生效
-
如果容器启动时后面加了启动参数命令,则会将CMD命令覆盖掉
docker run image ls -al #会将原CMD覆盖
-
docker run image -l
会报错 必须要完整的命令docker run image ls -al
ENTRYPOINT特点
docker run image -l
最后的 -l
命令会跟在原命令后面,生效
构建tomcat镜像
FROM centos
MAINTAINER peterven<121212@qq.com>
ADD OpenJDK8U-jdk_x64_linux_hotspot_8u282b08.tar.gz /usr/local
ADD apache-tomcat-9.0.45.tar.gz /usr/local
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk8u282-b08
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.45
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
EXPOSE 8080
CMD startup.sh && tail -f /usr/local/apache-tomcat-9.0.45/logs/catalina.out
docker build -t mytomcat -f mydockerfile .
docker build
最后的 .
号,其实是在指定镜像构建过程中的上下文环境的目录
发布镜像
hub.docker.com
- 注册账号
- 确定能登陆
- 发布
docker login -uxx -pxx
docker push 用户名/image:1.0
发布到阿里云的镜像仓库
sudo docker login --username=xxxregistry.cn-hangzhou.aliyuncs.com
sudo docker push --username=xxxregistry.cn-hangzhou.aliyuncs.com/repoxx/xxx:1.0
Docker网络
理解Docker0
容器内部网卡
- 容器外
ping
容器内 【可通】 - 容器间互
ping
【可通】
使用veth pair技术 简单理解就是一半网卡在容器内 一半在容器外
安装完docker就会生成一个docker0网卡
每启动一个容器,宿主机上会出现一个网卡,容器内也会有一个网卡,通过veth-pair技术桥接了网络,使得容器能和宿主机互通
Docker --link
通过 --link 可以不使用ip 而使用容器名来ping通
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 --link tomcat01 tomcat
docker exec -it tomcat02 ping tomcat01 #可通
docker exec -it tomcat01 ping tomcat02 #不可通
docker network ls
docker network inspect 365c8b3167c2
[
{
"Name": "bridge",
"Id": "365c8b3167c24be53d3f6b8c5e5f8cb335df24d092619c284675519602cab942",
"Created": "2021-04-27T21:30:12.459391064+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"07b4d9b34173fc36f2f97b12641e14d8bfce25dd2023750826b2b1ea234a5490": {
"Name": "tomcat02",
"EndpointID": "8a5aa6f3b55d1309a396a6787e45dc6393e1878e5ec70e1b0e00075c3743dd13",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"3cd721278aa3469f61eafbd0472fa24a39fc2bb30de0f9f094ad18fa781a06f5": {
"Name": "tomcat01",
"EndpointID": "412a25971c2195b132f1427ade1fd2609226ddfc3feab67952760fecbed87738",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
其实--link
就是在/etc/hosts
里配置了映射
但是还是比较麻烦,可以自定义网络,实现更便捷的容器互联
自定义网络
查看所有docker网络
网络模式
- bridge 桥接 docker(默认,自定义也是用这种模式)
- none 不配置网络
- host 和宿主机共享网络
- container 容器网络联通(用的少)
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
使用自定义网络启动容器
docker run -d -P --name tomcat01 --net mynet tomcat
docker run -d -P --name tomcat02 --net mynet tomcat
[peter@hadoop102 ~]$ docker network inspect mynet
[
{
"Name": "mynet",
"Id": "b5844ff709ca3c1661592c7308bcf63ecb8a536799ee6fb0b96d829e9bf0c964",
"Created": "2021-04-27T22:19:03.710481606+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"500c48d08e6190ce8b75e91900032367691cc64a02c48faefbba2b82d48d6f6e": {
"Name": "tomcat02",
"EndpointID": "fed42acaad05c471d4a52b9a585809fee4b9cf49445c4de73eb8c822f2aeff16",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"87ed6b15bc557d2c9d979a187224420ed2a688874c7cd9b64ac11429e4123241": {
"Name": "tomcat01",
"EndpointID": "2fcea1714ef68185f5b723072de99b2faaabce18b3734daa5b340d2999d5650d",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
可以看到增加了两个容器网卡信息
!!!不需要
--link
也能够使用容器名去ping
好处:
- 不同的集群使用不同的网络,保证集群是安全健康的
网络连通
两个不同的网卡间是如何连通
docker network connect [network] [container]
docker network connect mynet tomcat03
将某个容器加入到某个网卡中 实现互联 一个容器拥有了两个ip地址
部署Redis集群
redis网卡
docker network create redis --subnet 172.16.0.0/16
创建六个redis创建的脚本
#! /bin/bash
for port in $(seq 1 6);
do
sudo mkdir -p /home/redis/node-${port}/conf
sudo touch /home/redis/node-${port}/conf/redis.conf
cat << EOF >/home/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.16.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
启动redis
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /home/redis/node-1/data:/data \
-v /home/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.16.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /home/redis/node-2/data:/data \
-v /home/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.16.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /home/redis/node-3/data:/data \
-v /home/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.16.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /home/redis/node-4/data:/data \
-v /home/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.16.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /home/redis/node-5/data:/data \
-v /home/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.16.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /home/redis/node-6/data:/data \
-v /home/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.16.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
进入任意一个容器进行集群配置
redis-cli --cluster create 172.16.0.11:6379 172.16.0.12:6379 172.16.0.13:6379 172.16.0.14:6379 172.16.0.15:6379 172.16.0.16:6379 --cluster-replicas 1
Docker Compose
轻松、高效管理容器,定义运行多个容器。
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.
Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.
Using Compose is basically a three-step process:
- Define your app’s environment with a
Dockerfile
so it can be reproduced anywhere. - Define the services that make up your app in
docker-compose.yml
so they can be run together in an isolated environment. - Run
docker compose up
and the Docker compose command starts and runs your entire app. You can alternatively rundocker-compose up
using the docker-compose binary.
A docker-compose.yml
looks like this:
version: "3.9" # optional since v1.27.0
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
Compose重要的概念
- 服务service,容器、应用(web、redis、mysql)
- 项目project,一组关联的容器
安装Compose
yaml规则
# 3层
version: '' #版本
services: #服务
服务1: web
# 服务配置
images
build
network
......
服务2: redis
......
服务3: redis
# 其他配置
volumes:
networks:
configs:
官方文档
Compose file version 3 reference | Docker Documentation
常用命令
docker-compose up
docker-compose up --build 重新构建
docker-compose down
一键部署博客
version: "3.9"
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
Docker Swarm
docker 自带的集群管理
# 初始化集群
docker swarm init --advertise-addr x.x.x.x
# 获取令牌
docker swarm join-token manager
docker swarm join-token worker
# 离开集群
docker swarm leave
集群要最少3个节点, 不然无法使用
集群搭建好后,使用
docker service
命令
动态扩缩容、滚动更新
docker service create #启动应用
docker service ps [服务名] # 查看服务信息
docker service ls #查看集群情况
docker service update --replicas 3 [服务名] # 更新服务为3份
docker service scale [服务名]=3 #同上
docker service rm [服务名]
集群为3台,也可以docker service update --replicas 10 [服务名]