# Docker笔记

# Docker安装

  1. Alpine系统 (opens new window)
  2. 脚本安装Docker: curl https://get.docker.com | bash
  3. CentOS 环境Docker离线安装方式 (opens new window)
  4. Docker文件下载地址 (opens new window)
  5. Docker 中文指南 (opens new window)
  6. 两款Docker可视化工具 (opens new window)
  7. Docker+Jenkins+Nginx+Spring Boot 自动化部署项目 (opens new window)

在线安装:

# 安装依赖包
yum -y install yum-utils device-mapper-persistent-data lvm2

# 安装Docker
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 	# 配置安装源 			
yum list docker-ce.x86_64 --showduplicates | sort -r  	# 查看docker版本,选择对应的安装包
yum makecache fast && yum -y install docker-ce-18.09.3	

# 启动并验证Docker是否安装成功
systemctl daemon-reload && systemctl start docker	# 启动docker
systemctl enable docker.service		# 设置开机启动
docker version           # 查看docker版本信息

RPM参考命令:

rpm -qa docker*  # 查找当前系统安装以docker开头的rpm包
rpm -e docker-ce-17.03.2.ce-1.el7.centos.x86_64 # 卸载这个rpm安装包
rpm -e --nodeps docker*   # 卸载这个rpm安装包(不卸载依赖的包)
rpm -ivh docker/* --nodeps --force	# 安装docker目录下的rpm包

快速卸载Docker中镜像:

docker stop $(docker ps -a -q)	# 先停止镜像生成的容器,会返回容器id
docker stop $(docker ps -a | grep gcr | awk '{ print $1}') # # 按名称搜索特定容器进行删除  
docker rm $(docker ps -a -q)	# 再删除镜像生成的容器,会返回容器id
docker rm $(docker ps -a | grep gcr | awk '{ print $1}')
docker rmi 446380f4e90c		# 再删除镜像 
docker rmi -f $(docker images -a -q) # 清理所有镜像(包括中间镜像层)   
docker rmi -f $(docker images | grep gcr | awk '{ print $3}') # 按名称搜索特定镜像进行删除
docker rmi -f $(docker images | grep none | awk '{ print $3}') # 清理镜像

Docker常见命令

systemctl start|stop|status|restart|enable|daemon-reload docker  # 启动|停止|查看状态|重启|开机自启|重新载入
docker info  # 查看docker概要信息
docker stats # 显示统计的docker的CPU、内存、网络、IO情况
docker build -t runoob/ubuntu:v1 . 	# 使用Dockerfile编译创建一个镜像 t: tag 
docker login docker.io	# 登录hub.docker.com 授权位置文件:  /root/.docker/config.json
# 推送镜像
docker tag mych:0.0.1 dkgee/mych:0.0.1  # 给镜像重新打标签,先标记
docker push dkgee/mych:0.0.1 			# 再推送
docker --help  # 查看docker帮助信息【比较有用】
docker -v  		# 查看docker版本
docker run -v	# Docker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定。
如我要启动一个centos容器,宿主机的/test目录挂载到容器的/soft目录,可通过以下方式指定:
docker run -it -v /test:/soft centos /bin/bash
docker save -o ./ubuntu18.tar ubuntu:18.04 	# 导出docker镜像ubuntu:18.04到当前目录的ubuntu18.tar中
docker load --input ./ubuntu18.tar	# 从当前路径下ubuntu18.tar加载镜像
docker export <容器名> > <保存路径>  # 导出容器,例如docker export ubuntu18 > ./ubuntu18.tar
docker import <文件路径>  <容器名>  # 导入容器,docker import ./ubuntu18.tar ubuntu18
docker attach <容器名> # 进入容器,该命令通常用于进入后台已经在运行的容器
docker exec -it <容器名> <执行指令>  # 进入容器,同一个容器有不同的界面,进入容器后的界面不会受该容器的其他运行者的影响,建议使用该命令
docker exec -it ubuntu18 /bin/bash
docker exec -it --user root <container id> /bin/bash	# 切换到root用户登录
docker network ls	# 查看容器网络(容器间通信),默认bridge模式	https://www.cnblogs.com/zuxing/articles/8780661.html  
docker search wordpress	# 搜索镜像
docker inspect <image name> 	# 检查容器,会将容器的配置详情打印出来  docker inspect data|grep /var/lib/docker/volum
docker ps  		# 查看docker容器
docker stop $(docker ps -a -q)  # 停止所有容器
docker start <image name>  		# 启动容器
docker rm $(docker ps -a -q)	# 删除所有容器
docker images 	# 查看docker内镜像
docker logs  CONTAINER_ID # 查看容器日志, 参考https://www.cnblogs.com/gylhaut/p/9317843.html
docker rmi 	<image id>	# 通过image的id来指定删除镜像
docker run -d xxx	# 后台运行某个容器  -d:后台模式 -P:创建容器(容器内部端口随机映射到主机端口) -p:指定端口(容器内部端口指定映射到主机端口)
例如:docker run -d -P training/webapp python app.py	# 后台运行training目录下的webapp容器,并执行python app.py命令
docker run -d -p 5000:5000 training/webapp python app.py  
# 后台运行training目录下的webapp容器,容器内5000端口映射到主机5000端口,并执行python app.py命令
docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py
# 我们可以指定容器绑定的网络地址,比如绑定 127.0.0.1。【注意,此处可以映射到我们的服务器地址】
# docker run -d -p 10.3.211.247:19090:19090 training/webapp python app.py   就可以通过访问10.3.211.247:19090来访问容器的 5000 端口。
docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
# 指定端口使用udp协议,默认为tcp协议
docker port adoring_stonebraker 5000
# 查看容器端口绑定情况
docker run -d -P --name runoob training/webapp python app.py
# 当我们创建一个容器的时候,docker 会自动对它进行命名。另外,我们也可以使用 --name 标识来命名容器
docker ps -l
# 查看容器名称。
  1. 菜鸟教程之Docker命令大全 (opens new window)
  2. Docker容器之间端口映射 (opens new window)
  3. Dockerfile中CMD、ENTRYPOINT命令区别 (opens new window)
  4. 通过docker来编译Dockerfile构建镜像: docker build -t app_dir ./Dockerfile
  5. Docker环境探测 (opens new window)

# Docker镜像组件

国内较快的镜像原地址
Docker 官方中国区 https://registry.docker-cn.com 网易 http://hub-mirror.c.163.com
ustc https://docker.mirrors.ustc.edu.cn

指定镜像源地址进行拉取
docker pull registry.docker-cn.com/myname/myrepo:mytag

Redis

## 单节点
docker pull redis:3.2
# 无密码模式 以appendonly备份,该备份是采用增量保存写命令方式备份
docker run -p 6379:6379 --name myredis -v $PWD/data:/data  -d redis:3.2 redis-server --appendonly yes
# 有密码模式 xxxxxxx 为要设置的密码
docker run -p 6379:6379 --name myredis -v $PWD/data:/data  -d redis:3.2 redis-server --appendonly yes --requirepass "xxxxxxx"
docker exec -it myredis redis-cli
## 集群模式【只能用于测试环境,不能用于生产环境】
docker pull tommy351/redis-cluster
docker run --name myredisc -v $PWD/data:/data -p 7000:7000 -p 7001:7001 -p 7002:7002 -p 7003:7003 -p 7004:7004 -p 7005:7005 -d tommy351/redis-cluster
docker exec -it myredis /bin/sh
docker exec -it myredisc redis-cli -h 49.233.170.108 -p 7000 -c
# 解决公网访问出现 redis TTL exhausted.异常信息问题,使用CLUSTER_ANNOUNCE_IP发布。
docker run --name myredisc -v $PWD/data:/data -p 7000:7000 -p 7001:7001 -p 7002:7002 -p 7003:7003 -p 7004:7004 -p 7005:7005 \
-e CLUSTER_ANNOUNCE_IP=127.0.0.1 -d tommy351/redis-cluster	

Mysql

docker pull mysql:5.6
docker pull kiratalent/mysql:5.7
docker run -p 3306:3306 --name mymysql -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/var/log/mysql -v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
docker exec -it mymysql mysql -uroot -p123456

# docker 修改mysqld配置重启失败后,排查需要修改目录权限,使用下面方式重启。
# 这种在后面以exec交互命令进入容器,执行目录赋权命令即可。或者使用在主机使用"chown -R polkitd:ssh_keys logs"
docker start mymysql && docker exec -it mymysql chown -R mysql:mysql /var/log/mysql/

# mysql开启binlog,修改mysql配置,如/etc/mysql/my.cnf,增加binlog配置。	
log-bin = /var/log/mysql/mysql-bin.log
expire-logs-days = 14
max-binlog-size = 500M
server-id = 1

Zookeeper

docker pull zookeeper
docker run --name myzk -p 2181:2181 -d zookeeper
docker run --name myzk -p 2181:2181 --network host -d zookeeper 【使用主机网络】
docker exec -it myzk /bin/bash

# 重要提示,使用的zookeeper,必须是 zookeeper:tag系列,不是能jplock/zookeeper,这个镜像集群有问题!!!!

Kafka

集群模式搭建参考 (opens new window)

docker pull wurstmeister/kafka			
docker run -d --name mykafka --publish 9092:9092 --link myzk --env KAFKA_ZOOKEEPER_CONNECT=myzk:2181 --env KAFKA_ADVERTISED_HOST_NAME=localhost --env \
KAFKA_ADVERTISED_PORT=9092 --volume /etc/localtime:/etc/localtime wurstmeister/kafka:latest

docker exec -it kafka /bin/bash
bin/kafka-topics.sh --create --zookeeper myzk:2181 --replication-factor 1 --partitions 1 --topic mykafka3
bin/kafka-console-producer.sh --broker-list localhost:9092 --topic mykafka3
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic mykafka3 --from-beginning 【注意kakfa低版本问题】

bin/kafka-topics.sh --create --zookeeper myzk:2181 --replication-factor 1 --partitions 1 --topic TopicDeviceLog
bin/kafka-topics.sh --create --zookeeper myzk:2181 --replication-factor 1 --partitions 1 --topic TopicIpAccessLog

docker exec -it mykafka /opt/kafka_2.12-2.3.0/bin/kafka-topics.sh --create --zookeeper myzk:2181 --replication-factor 1 --partitions 1 --topic TopicDeviceLog
docker exec -it mykafka /opt/kafka_2.12-2.3.0/bin/kafka-topics.sh --create --zookeeper myzk:2181 --replication-factor 1 --partitions 1 --topic TopicIpAccessLog

docker exec -it ciot_mykafka_1 /opt/kafka_2.12-2.3.0/bin/kafka-topics.sh --create --zookeeper 172.30.154.245:2181 --replication-factor 1 --partitions 1 --topic TopicDeviceLog

#启动Docker中kafka生产者和消费端(注意kafka中版本号,可能会因为镜像更新而变化)
docker exec -it mykafka /opt/kafka_2.12-2.4.0/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic TopicMessageLog
docker exec -it mykafka /opt/kafka_2.12-2.4.0/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic TopicMessageLog --from-beginning 

#使用云服务器部署Kafka节点,KAFKA_ADVERTISED_HOST_NAME为内网IP、KAFKA_ADVERTISED_LISTENERS为外网IP
docker run -d --name mykafka --publish 9092:9092 --link myzk --env KAFKA_ZOOKEEPER_CONNECT=myzk:2181 --env KAFKA_ADVERTISED_HOST_NAME=172.17.0.10 --env \
KAFKA_ADVERTISED_PORT=9092 --env KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://122.51.101.124:9092 --volume /etc/localtime:/etc/localtime wurstmeister/kafka:latest

# kafka-manager有图形化UI,可以方便的监控集群状态 项目地址:https://github.com/yahoo/CMAK
docker run -itd --restart=always --name=kafka-manager -p 9000:9000 -e ZK_HOSTS="zoo1:2181,zoo2:2181,zoo3:2181" sheepkiller/kafka-manager

# kafka队列开始读取消息,每次重启后,都会从开始处读取消息,可能会导致重复消息数据
# auto.offset.reset --earliest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费 
# auto.offset.reset --latest : 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据 

# 重要提示,使用的zookeeper,必须是 zookeeper:tag系列,不是能jplock/zookeeper,这个镜像集群有问题!!!!

Clickhouse&Tabix

docker pull yandex/clickhouse-server
docker pull yandex/clickhouse-client

## 只挂载存储
docker run -d --name mych --ulimit nofile=262144:262144 -p 8123:8123 --volume=$PWD/database:/var/lib/clickhouse yandex/clickhouse-server

## 挂载配置和存储
docker run -d --name mych --ulimit nofile=262144:262144 -v $PWD/database:/var/lib/clickhouse \
-v $PWD/config/config.xml:/etc/clickhouse-server/config.xml yandex/clickhouse-server

## 客户端
docker run -it --rm --link mych:clickhouse-server yandex/clickhouse-client --host clickhouse-server 
docker run -it --rm yandex/clickhouse-client --host 10.92.8.210

## Tabix(clickhouse 查询操作界面)
docker pull spoonest/clickhouse-tabix-web-client
docker run -d -p 8080:80 spoonest/clickhouse-tabix-web-client

ELK

## Elasticsearch
docker pull elasticsearch:6.7.0
docker run --name elasticsearch -d -p 9200:9200 -p 9300:9300 elasticsearch:6.7.0

docker run -d -p 9202:9200 -p 9302:9300 --link es1\
--name es2 -e cluster.name=meitu -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e xpack.security.enabled=false\
-e discovery.zen.ping.unicast.hosts=es1 docker.elastic.co/elasticsearch/elasticsearch:5.6.3

docker run --rm -v /opt/elk/es/data:/usr/share/elasticsearch/data elasticsearch:6.7.0 /bin/bash -c 'ls -al /usr/share/elasticsearch/'

集群搭建参考地址: https://blog.csdn.net/belonghuang157405/article/details/83301937
1. 本地映射data目录权限需要修改	
	chmod 775  /opt/elk/es/data && echo "vm.max_map_count=655360" >> /etc/sysctl.conf && /sbin/sysctl -p		
2. 启动docker-compose参考
version: '2'
	services:
		es:
		image: elasticsearch:6.7.0
		ports:
			- "9200:9200"
			- "9300:9300"
		environment:
			- xpack.security.enabled=false
		volumes:
			- /opt/elk/es/es.yml:/usr/share/elasticsearch/config/elasticsearch.yml
			- /opt/elk/es/data:/usr/share/elasticsearch/data
			- /opt/elk/es/plugins:/usr/share/elasticsearch/plugins
		network_mode: "bridge"
3. 注意报错: Caused by: java.nio.file.AccessDeniedException: /usr/share/elasticsearch/data/nodes
	chmod 775 /opt/elk/es/data

## Logstash
docker pull logstash:6.5.2			
docker run -d -p 9600:9600 -it -v $PWD/config/:/usr/share/logstash/config/  logstash:6.5.2		
【装插件】
docker run -it --rm logstash:6.5.2  logstash-plugin install  logstash-input-jdbc  
docker run -it --rm mylogstash:1.0.0  logstash-plugin install  logstash-input-nsq
【本地目录安装】
docker run -it --rm -v $PWD/plugin/:/opt/plugin/ logstash:6.5.2 logstash-plugin install file:///opt/plugin/logstash-filter-prune-6.5.2.zip
docker run -it --rm logstash:5.6.10 -f /dir/config.conf -v /config/dir:/dir	
如果需要安装多个插件需要使用Dockerfile重新创建镜像,例如
FROM logstash:6.5.2
ADD plugin /opt/plugin
RUN logstash-plugin install file:///opt/plugin/logstash-filter-mutate-6.5.2.zip
RUN logstash-plugin install file:///opt/plugin/logstash-filter-prune-6.5.2.zip
RUN logstash-plugin install file:///opt/plugin/logstash-input-kafka-6.5.2.zip
RUN logstash-plugin install file:///opt/plugin/logstash-output-clickhouse-6.5.2.zip

## Kibana【界面】
docker pull kibana:6.7.0
docker run -d --name kibana -e ELASTICSEARCH_HOSTS=http://172.30.154.241:9200,http://172.30.154.244:9200,http://172.30.154.245:9200 -p 5601:5601 kibana:6.7.0
docker run -d --name kibana -e ELASTICSEARCH_HOSTS=http://172.30.154.241:9200 -p 5601:5601 kibana:6.7.0

## elasticsearch-head【界面】
docker pull leeyaf/elasticsearch-head:v1.0
docker run --name elasticsearch-head -d -p 9100:9100 leeyaf/elasticsearch-head:v1.0
docker exec -it elasticsearch-head /bin/bash

Jenkins(建议使用rpm安装在物理机上,不要使用Docker镜像)

docker pull jenkins/jenkins:lts  #使用这个版本
docker run --name myjk -p 8080:8080 -p 50000:50000 -d jenkins/jenkins:lts

jenkins镜像需要自己制作	50000为agent代理控制端口	jdk环境配置	maven环境配置
docker run -d -p 8080:8080 -p 50000:50000 -v /home/jenkins:/var/jenkins_home -v /usr/local/maven3:/usr/local/maven3 \ 
-v /usr/java/jdk1.8.0_201:/usr/java/jdk1.8.0_201 -v /usr/bin/mvn/:/usr/bin/mvn/ --name=jenkinsnew6 jenkinsnew
# 需要把自带的jdk、maven安装路径映射进docker容器中
在jenkins shell中执行没有加载/etc/profile .bash_profile中的环境变量	

Nexus3

docker pull sonatype/nexus3

Nginx

# 参考: https://blog.csdn.net/sunt2018/article/details/85001485
docker pull nginx
# 创建挂载目录
mkdir -p /data/nginx/{conf,conf.d,html,logs}	
# 在 conf 中 编写 nginx.conf 配置文件	
docker run --name mynginx -p 80:80  \
-v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf  \
-v /data/nginx/logs:/var/log/nginx  \
-v /data/nginx/html:/usr/share/nginx/html \
-d nginx:latest

制作镜像并传播示例

## 提交自制镜像
docker commit -a "dkgee" -m "ciot" 7ec361637ebb mych:1.0.0
## 导出镜像到本地
docker save mych:0.0.1 -o /opt/docker/clickhouse/mych.tar
tar -zcvf clickhouse.tar.gz clickhouse
# 将clickhouse.tar.gz复制到其他机器
tar -zxvf clickhouse.tar.gz
## 导入镜像
docker load --input ./mych.tar
docker run -d --name mych --ulimit nofile=262144:262144 -p 8123:8123 --volume=$PWD/database:/var/lib/clickhouse mych:0.0.1
docker load --input ./mych-client.tar
docker run -it --rm --link mych:clickhouse-server yandex/clickhouse-client --host clickhouse-server 

ActiveMQ

# 拉取ActiveMQ
docker pull rmohr/activemq:latest
# 8161为UI端口,admin/admin
docker run -p 61616:61616 -p 8161:8161 rmohr/activemq
  1. Docker搭建RocketMQ (opens new window)

# App部署到Docker

  1. spring boot应用发布到docker(完整版) (opens new window)
  2. springboot2.x+docker部署 (opens new window)
  3. Maven中最强大的Docker插件 (opens new window)
  4. MVN编译路径:mvn clean install -DskipTests docker:build

配置 Docker远程访问API:

docker-maven-plugin 插件是使用的 Docker Remote API 进行远程提交镜像的,docker 默认并没有开启该选项,直接修改 docker 服务配置即可, Centos 7 配置文件位于:/usr/lib/systemd/system/docker.service 直接在 ExecStart 启动参数的 /usr/bin/dockerd 后面添加以开启 TCP 连接:-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock Docker 会根据 Dockerfile 生成镜像时自动下载需要的依赖 IDEA有Docker插件可用

镜像加速

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://adabmonl.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
1
2
3
4
5
6
7
8

# Volumes

  1. Docker数据存储之Volumes详解 (opens new window)
  2. Volumes使用场景 (opens new window)

Volumes特点

  1. 数据卷可以在容器间共享和重用
  2. 对数据卷的写入操作,不会对镜像有任何影响
  3. 数据卷默认会一直存在,即使容器被删除。使用数据卷的目的是持久化容器中的数据,以在容器间共享或者防止数据丢失(写入容器存储层的数据会丢失)

使用数据卷的步骤一般分为两步:

  1. 创建一个数据卷
  2. 使用-v或--mount参数将数据卷挂载容器指定目录中,这样所有该容器针对该指定目录的写操作都会保存在宿主机上的Volume中
## 查看数据卷
docker volume ls

## 统计数据卷大小
du -sh /var/lib/docker/volumes/

# 检查某个(my-vol)数据卷
docker volume inspect my-vol

# 删除一个Volume
docker volume rm my-vol

# 删除所有未使用的Volumes
docker volume prune
1
2
3
4
5
6
7
8
9
10
11
12
13
14

使用只读数据卷:

# 示例一
$ docker run -d \
 --name=nginxtest \
 --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \	# 此处为只读
 nginx:latest
 
# 示例二
$ docker run -d \
 --name=nginxtest \
 -v nginx-vol:/usr/share/nginx/html:ro \	# 只读
 nginx:latest

1
2
3
4
5
6
7
8
9
10
11
12

Volumes使用场景

  1. 在多个容器间共享数据。
  2. 无法确保Docker主机一定拥有某个指定的文件夹或目录结构,使用Volumes可以屏蔽这些宿主机差异。
  3. 当你希望将数据存储在远程主机或云提供商上。
  4. 当你希望备份,恢复或者迁移数据从一台Docker主机到另一台Docker主机,Volumes是更好的选择。

# 小知识点

  1. “Java 将服务器类机器定义为具有2个 CPU 和 2GB 内存,默认堆大小为物理内存的1/4。”,这句话反映出:如果服务器硬件(包括虚拟OS)资源比较丰富,可以使用容器的方式对服务器资源进行均衡分配(例如限制cpu个数、内存大小),从而实现多台“服务器”效果。
  2. 容器中 Java 应用程序的内存和 CPU 如何分配? (opens new window)
  3. 限制容器对CPU的使用 - 每天5分钟玩转 Docker 容器技术(28) (opens new window)
  4. 一个docker host上会运行若干容器,每个容器都需要CPU、内存和IO资源。对 KVM,VMware等虚拟化技术,用户可以控制分配多少CPU、内存资源给每个虚拟机。对于容器,Docker也提供了类似的机制避免某个容器因占用太多资源而影响其他容器乃至整个host的性能。
  5. Docker 安装时会创建一个 命名为 docker0 的 linux bridge。如果不指定--network,创建的容器默认都会挂到 docker0 上。
  6. Docker 提供三种 user-defined 网络驱动:bridge, overlay 和 macvlan。overlay 和 macvlan 用于创建跨主机的网络。
上次更新: 2020-08-19 09:41:47