面试题
1.谈谈docker虚悬镜像是什么?
仓库名和标签都是none的镜像
1.docker’命令
1.启动命令
启动docker: systemctl start docker
停止docker: systemctl stop docker
重启docker: systemctl restart docker
查看docker状态: systemctl status docker
开机启动: systemctl enable docker
查看docker概要信息: docker info
查看docker总体帮助文档: docker --help
查看docker命令帮助文档: docker 具体命令 --help
2.镜像命令
列出本地主机上的镜像:docker images
参数:-a :列出本地所有的镜像(含历史映像层)
-q :只显示镜像ID。
查找某个XXX镜像名:docker search
只列出N个镜像,默认25个:docker search --limit 5 redis 列出5个
下载镜像: docker pull 某个XXX镜像名字:TAG 没有tag就默认为最新版
查看镜像/容器/数据卷所占的空间:docker system df
删除镜像: docker rmi -f(代表强制删除) 镜像ID
删除多个: docker rmi -f 镜像名1:TAG 镜像名2:TAG
删除全部: docker rmi -f $(docker images -qa)
启动镜像:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS参数:
--name="容器新名字" 为容器指定一个名称;
-d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行);
-i:以交互模式运行容器,通常与 -t 同时使用;
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;也即启动交互式容器(前台有伪终端,等待交互);
-P: 随机端口映射,大写P
-p: 指定端口映射,小写p
注意:如果镜像不是默认的版本,启动时必须加上版本号;比如:docker run -d redis:6.0.8
3.容器命令
启动已停止运行的容器: docker start 容器ID或者容器名
停止容器: docker stop 容器ID或者容器名
强制停止容器: docker kill 容器ID或容器名
删除容器: docker rm 容器ID
删除所有: docker rm -f $(docker ps -a -q)
列出正在运行的容器: docker ps
列出所有的容器(包括不运行): docker ps -n 数量
退出容器: exit 容器停止
ctrl + q +p 容器不停止
重新进入docker容器交互式页面: 推荐使用:docker exec -it 容器ID bash
第二种方式:docker attach 容器ID
区别:attach 直接进入容器启动命令的终端,不会启动新的进程,用exit退出,会导致容器的停止。
exec 是在容器中打开新的终端,并且可以启动新的进程,用exit退出,不会导致容器的停止。
复制容器内文件到主机:docker cp 容器ID:容器内路径 目的主机路径
导出容器:docker export 容器ID > 文件名.tar
导入容器:cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
查看容器卷的挂载信息: docker inspect 容器id
4.commit操作
通过扩展现有的镜像,创建一个新的镜像
案例:
默认的ubuntu镜像是不带vim的,安装vim,
执行命令: apt-get update
安装vim: apt-get -y install vim
提交镜像: docker commit -m="vim cmd add ok" -a="root" 7463cb99a705 myubuntu:1.1
2.镜像发布
1.发布到阿里云
发布操作
1.登录操作 docker login --username=z17596037870 registry.cn-hangzhou.aliyuncs.com
2.修改名字 docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/bj_powernode/myubuntu:[镜像版本号]
3.发布 docker push registry.cn-hangzhou.aliyuncs.com/bj_powernode/myubuntu:[镜像版本号]
拉取操作
要登陆
docker pull registry.cn-hangzhou.aliyuncs.com/bj_powernode/myubuntu:[镜像版本号]
2.发布到私有库
1.创建私有库
1.下载镜像 docker pull registry
2.运行私有库registry(相当于本地有个私有的Docker hub)
docker run -d -p 5000:5000 -v /docker/myregistry/:/tmp/registry --privileged=true registry
3.查看私有库有什么镜像 curl -XGET http://192.168.26.31:5000/v2/_catalog
4.修改镜像名字 docker tag 镜像名字:Tag host:port/Repository:Tag
例如 docker tag ubuntu:1.2 192.168.26.31:5000/ubuntu:1.2
5.修改配置文件 vim /etc/docker/daemon.json 加上"insecure-registries": ["192.168.111.162:5000"]
{
"registry-mirrors": ["https://4pydv81q.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.111.162:5000"]
}
6.发布 docker push 192.168.26.31:5000/ubuntu:1.2
3.docker常规安装
1.tomcat
如果是10.0以上版本
需要把容器中的 /usr/local/tomcat下的webapps删掉,并把webapps.dist目录换成webapps
启动:docker run -it -p 8080:8080 tomcat
2.mysql
1.mysql5.7
1.下载 docker pull mysql:5.7
2.启动 docker run -d -p 3306:3306 --privileged=true -v /docker/mysql5.7/log:/var/log/mysql -v /docker/mysql5.7/data:/var/lib/mysql -v /docker/mysql5.7/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name=mysql mysql:5.7
3.mysql 5.7编码问题,向表中插入中文会失败;
解决: 在/docker/mysql/conf下新建my.cng文件
如下配置:
[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
通过容器卷自动同步给mysql5.7容器
zookeeper
docker run -d -p 2181:2181 --privileged=true -v /docker/mydata/zookeeper/conf:/zookeeper-3.4.14/conf --name zookeeper-3.4.14 zookeeper:3.4.14
2.mysql8.0
直接下载即可 docker pull mysql
不存在编码问题,不需要修改配置文件
3.redis
1.下载 docker pull redis:6.0.8
2.修改配置文件
a:允许redis外地连接 必须注释掉 # bind 127.0.0.1
b:daemonize no
将daemonize yes注释起来或者 daemonize no设置,因为该配置和docker run中-d参数冲突,会导致容器一直启动失败
3.启动 docker run -p 6379:6379 --name myr3 --privileged=true -v /docker/redis/redis.conf:/etc/redis/redis.conf -v /docker/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
4.Nacos
1.单机模式
挂载会出错,不知道原因
docker run -d \
-e MODE=cluster \
-e PREFER_HOST_MODE=hostname \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.190.128 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=123456 \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-p 8848:8848 \
--name nacos-mysql \
--restart=always \
nacos/nacos-server:1.4.1
2.集群模式
docker run -d \
-e PREFER_HOST_MODE=hostname \
-e MODE=cluster \
-e NACOS_APPLICATION_PORT=8849 \
-e NACOS_SERVERS="192.168.190.128:8848,192.168.190.128:8849,192.168.190.128:8850" \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.190.128 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=123456 \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e NACOS_SERVER_IP=192.168.190.128 \
-e JVM_XMS=200m \
-e JVM_XMX=200m \
-e JVM_XMN=150m \
-p 8849:8849 \
--name nacos49 \
nacos/nacos-server:1.4.1
使用nginx
docker run -d --privileged=true -v /docker/mydata/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -p 8080:8080 --name myNginx nginx
配置文件:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
upstream nacos{
server 192.168.190.128:8848;
server 192.168.190.128:8849;
server 192.168.190.128:8850;
}
server {
listen 8080;
#server_name localhost;
server_name 192.168.190.128;
location /nacos {
proxy_pass http://nacos;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
5.ElasticSearch
docker run --name elasticsearch -p 9200:9200 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /docker/mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /docker/mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /docker/mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.190.128:9200 -p 5601:5601 \
-d kibana:7.4.2
6.Nginx
docker run -p 80:80 --name guli-nginx \
-v /docker/mydata/guli-nginx/html:/usr/share/nginx/html \
-v /docker/mydata/guli-nginx/logs:/var/log/nginx \
-v /docker/mydata/guli-nginx/conf:/etc/nginx \
-d nginx
4.docker复杂安装
1.Mysql主从复制
1.建立主服务器3307
1.构建容器
docker run -p 3307:3306 --name mysql-master -v /docker/mysql-cluter/mysql-master/log:/var/log/mysql -v /docker/mysql-cluter/mysql-master/data:/var/lib/mysql -v /docker/mysql-cluter/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
2.修改配置文件
进入/docker/mysql-cluter/mysql-master/conf目录 vim my.cnf
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=1
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能
log-bin=master-log
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
修改完重启 docker restart mysql-master
3.master容器实例内创建数据同步用户
docker exec -it mysql-master /bin/bash
mysql -uroot -p123456
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
2.建立主服务器3308
1.构建容器
docker run -p 3308:3306 --name mysql-slave -v /docker/mysql-cluter/mysql-slave/log:/var/log/mysql -v /docker/mysql-cluter/mysql-slave/data:/var/lib/mysql -v /docker/mysql-cluter/mysql-slave/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
2.修改配置文件
进入/docker/mysql-cluter/mysql-slave/conf目录 vim my.cnf
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=2
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=slave-log
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1
重启 docker restart mysql-slave
3.在从数据库中配置主从复制
在主数据库中查看主从同步状态 show master status;
注意pos,配置master_log_pos=154时,pos等于主数据库的;
进入从数据库
docker exec -it mysql-slave/bin/bash
mysql -uroot -p123456
change master to master_host='192.168.190.128', master_user='slave', master_password='123456', master_port=3307, master_log_file='master-log.000002', master_log_pos=154, master_connect_retry=30;
4.开启同步
start slave;
查看状态
show slave status \G;
2.Redis集群
1.配置集群
1.启动集群
docker run -d --name redis-node-1 --net host --privileged=true -v /docker/redis-share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
docker run -d --name redis-node-2 --net host --privileged=true -v /docker/redis-share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
docker run -d --name redis-node-3 --net host --privileged=true -v /docker/redis-share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
docker run -d --name redis-node-4 --net host --privileged=true -v /docker/redis-share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384
docker run -d --name redis-node-5 --net host --privileged=true -v /docker/redis-share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385
docker run -d --name redis-node-6 --net host --privileged=true -v /docker/redis-share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
2.构建集群关系
1.启动其中一个redis
docker exec -it redis-node-1 bash
2.构建主从关系
redis-cli --cluster create 192.168.190.128:6381 192.168.190.128:6382 192.168.190.128:6383 192.168.190.128:6384 192.168.190.128:6385 192.168.190.128:6386 --cluster-replicas 1
3.查看主从关系
redis-cli --cluster check 192.168.190.128:6381
在主机内使用: cluster nodes
4.启动主机
redis-cli -p 6381 -c
-c :必须加,如果不加 添加数据时,分配的地址号超过了该主机,就会添加失败
5.容错切换迁移
如果主机宕机,从机会上位.即使主机恢复,从机依旧变成主机, 主机变成从机
2.主从扩容
1.新增两个节点
6387
docker run -d --name redis-node-7 --net host --privileged=true -v /docker/redis-share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387
6388
docker run -d --name redis-node-8 --net host --privileged=true -v /docker/redis-share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
2.将6387作为master加入原集群
1.进入6387内部
docker exec -it redis-node-7 bash
2.将新增的6387作为master节点加入集群
redis-cli --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381
redis-cli --cluster add-node 192.168.26.31:6387 192.168.26.31:6381
3.第一次查看集群情况
redis-cli --cluster check 真实ip地址:6381
redis-cli --cluster check 192.168.26.31:6381
还没有槽位:slots为零
4.重新分配槽位
重新分派槽号
命令:redis-cli --cluster reshard IP地址:端口号
redis-cli --cluster reshard 192.168.26.31:6381
5.第二次查看槽位
redis-cli --cluster check 真实ip地址:6381
redis-cli --cluster check 192.168.26.31:6381
每个主机匀(yun)给了6387一点
3.将6388作为从机,加入6387
1.将6388作为从机,加入6387
命令:redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
redis-cli --cluster add-node 192.168.26.31:6388 192.168.26.31:6387 --cluster-slave --cluster-master-id f43b8a25585b6d32e2d74ac679d775dd6876f1de-------这个是6387的编号,按照自己实际情况
2.第三次查看槽位
redis-cli --cluster check 真实ip地址:6381
redis-cli --cluster check 192.168.26.31:6381
3.主从缩容
1.将6388删除
命令:redis-cli --cluster del-node ip:从机端口 从机6388节点ID
redis-cli --cluster del-node 192.168.26.31:6388 b3e9f686fde65bdc678e1a4afac02d34d454d1e0
检查是否删除成功:
redis-cli --cluster check 192.168.26.31:6381
2.重新分配槽位
redis-cli --cluster reshard 192.168.26.31:6381
3.查看槽位
redis-cli --cluster check 192.168.26.31:6381
4.删除6387
命令:redis-cli --cluster del-node ip:端口 6387节点ID
redis-cli --cluster del-node 192.168.26.31:6387 f43b8a25585b6d32e2d74ac679d775dd6876f1de
检查是否删除成功:
redis-cli --cluster check 192.168.26.31:6381
5.DockerFile解析
1.案例
1.给centos安装java8和ifconfig
1.编写DockerFile文件
FROM centos
#作者
MAINTAINER zzyy<zzyybs@126.com>
#进入容器后的落脚点
ENV MYPATH /usr/local
#$MYPATH 代表引用上面的MYPATH路径
WORKDIR $MYPATH
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 80
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
2.构建
docker build -f dockerfile的文件路径(名称为Dockerfile,可以省略这个参数) -t 新镜像名字:TAG . 注意:后面有个点
例如: docker build -t centos:1.1 .
docker history 镜像id 查看镜像的历史版本
2.给centos加入tomcat和jdk
FROM centos:centos7
MAINTAINER zxy<85766@qq.com>
ADD jdk-8u171-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.65.tar.gz /usr/local
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.65
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.65
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.65/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.65/bin/logs/catalina.out
2.部署springboot项目
1.编写Dockerfile文件
FROM java:8
#只复制jar文件,类似ADD,拷贝文件和目录到镜像中。
COPY *.jar /app.jar
#输出一句话
CMD ["--server.port=8080"]
#暴露端口
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
2.构建镜像
docker build -t springboot-test .
3.启动镜像
docker run -d -p 8080:8080 --name springboot-test 镜像名称/id
4.访问项目
curl localhost:8080/hello
6.Docker轻量级可视化工具Portainer
账号:admin
密码:12345678
1.安装
docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
curl -L "https://github.com/docker/compose/releases/download/v2.10.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
curl -L "https://get.daocloud.io/docker/compose/releases/download/v2.10.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
2.使用
在这里选择容器卷
7.Docker网络
1.理解docker0
进入tomcat容器
docker exec -it 7446bfac0ada bash
在里面 输出 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
22: eth0@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
eth0@if23中172.17.0.3就是该容器的ip
Linux主机可以ping通该容器
容器之间也可以ping通
原理:
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair技术
7.compose编排
docker-compose文档地址https://docs.docker.com/compose/gettingstarted/
1.体验官网例子
1.应用 app.py
2.Dockerfile 应用打包为镜像
3.Docker-compose.yml文件(定义整个服务需要的环境. web,redis) 完整的上线服务
3.启动compose项目 命令: docker-compose up
2.compose编写规则
Compose常用命令
docker-compose -h # 查看帮助
docker-compose up # 启动所有docker-compose服务
docker-compose up -d # 启动所有docker-compose服务并后台运行
docker-compose down # 停止并删除容器、网络、卷、镜像。
docker-compose exec yml里面的服务id # 进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bash
docker-compose ps # 展示当前docker-compose编排过的运行的所有容器
docker-compose top # 展示当前docker-compose编排过的容器进程
docker-compose logs yml里面的服务id # 查看容器输出日志
docker-compose config # 检查配置
docker-compose config -q # 检查配置,有问题才有输出
docker-compose restart # 重启服务
docker-compose start # 启动服务
docker-compose stop # 停止服务
docker-compose.yaml
#三层
version: '' #版本
services: '' #服务
服务1: web
#服务配置
images
build
network
服务二: redis
...
服务三: mysql
....
services:
db:
# We use a mariadb image which supports both amd64 & arm64 architecture
image: mysql:5.7
# If you really want to use MySQL, uncomment the following line
#image: mysql:8.0.27
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=somewordpress
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress
expose:
- 3306
- 33060
wordpress:
image: wordpress:latest
volumes:
- wp_data:/var/www/html
ports:
- 80:80
restart: always
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- WORDPRESS_DB_NAME=wordpress
volumes:
db_data:
wp_data: