一、Docker是什么?
Docker 是一个开源的应用容器引擎,让开发者可以打包应用以及依赖包到一个可移植的镜像中,然后发布到Linux或Windows操作系统的机器上。
ex: 前端Vue需要build打包在nginx环境部署;
后端Java需要java -jar app.jar运行;
前后端需要安装不同的环境去部署运行。
这个时候我们可以通过docker容器统一的环境去一键运行发布这些应用docker run ...。
Docker 包括三个基本概念:
- 镜像(Image):一个特殊文件系统。ex: ubuntu系统。
- 容器(Container):容器是镜像运行时的实体。容器可以被创建、启动、停止、删除等。
- 仓库(Repository):保存镜像。 ex: https://hub.docker.com public(共有仓库):免费上传、下载公开的镜像。 private(私有仓库):需要认证才能上传、下载镜像。
二、Docker安装与卸载
可参考 https://docs.docker.com/engine/install/centos tips: 这里安装基于 CentOS Linux release 7.6.1810 (Core)
1、安装
# 配置yum源sudo yum install -y yum-utilssudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 通过yum源安装docker# sudo yum -y install docker# 指定版本安装sudo yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io-1.4.6# 启动dockersudo systemctl start docker# 重启docker sudo systemctl restart docker# 开机自启sudo systemctl enable docker# 设置开机自启 & 现在启动sudo systemctl enable --now docker# 查看运行情况sudo systemctl status docker# 测试docker run --rm alpine ping -c 5 baidu.com
2、配置镜像加速器
# 修改daemon配置文件`/etc/docker/daemon.json`sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{ "registry-mirrors": ["加速器地址"]}EOFsudo systemctl daemon-reloadsudo systemctl restart docker# 查看 `Registry Mirrors`docker info
3、卸载
# 查看yum安装的docker软件包yum list installed |grep docker# 删除相关软件包yum -y remove docker* containerd.io# 删除关联数据rm -rf /var/lib/dockerrm -rf /var/lib/containerd
三、Docker运行Nginx
# 拉取镜像docker pull nginx# 运行# –name 定义一个容器的名字,如果在执行docker run时没有指定Name,那么deamon会自动生成一个随机数字符串当做UUID。# -d 标识是让 docker 容器在后台运行。# -p 标识通知 Docker 将容器内部使用的网络端口映射到我们使用的主机上。docker run --name nginx -d -p 8080:80 nginx
访问 http://127.0.0.1:8080
四、Docker运行Java项目
# docker拉取java jdk环境docker pull java:latest# 运行项目# 1、原生jar运行方式java -jar xx.jar --spring.profiles.active=prod# 2、java镜像环境运行方式docker run -d -p 3001:3001 --restart=always -v /zhengqingya/code/demo/app.jar:/tmp/app.jar --name springboot java:latest java -jar /tmp/app.jar# 3、可远程调试运行方式docker run -d -p 5000:5000 -p 50001:50001 --name demo \-v /zhengqingya/code/demo/app.jar:/tmp/app.jar \java:latest \java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=50001 -jar /tmp/app.jar --spring.profiles.active=prod# 4、从镜像仓库拉取运行方式docker run -d -p 5000:5000 -p 50001:50001 \-e PROFILE=prod \--restart always \--name demo \registry.cn-hangzhou.aliyuncs.com/zhengqing/demo# arthas 相关docker exec -it demo /bin/sh -c "wget https://alibaba.github.io/arthas/arthas-boot.jar && java -jar arthas-boot.jar"docker exec -it demo /bin/sh -c "java -jar /opt/arthas/arthas-boot.jar"
五、Docker常用命令
# 查看当前docker版本docker -v# 列出容器 -- 仅运行的容器docker ps # 列出容器 -- 包含停止的容器docker ps -a# 查看当前本地所有镜像docker images# 启动容器docker start 容器id# 重启容器docker restart 容器id# 杀掉一个运行中的容器docker kill -s KILL 容器id# 停止容器 docker stop 容器id# 删除容器docker rm 容器id# 删除一个或多少容器。-f :通过SIGKILL信号强制删除一个运行中的容器-l :移除容器间的网络连接,而非容器本身-v :-v 删除与容器关联的卷docker rm -f xx、xx2# 删除镜像 【 顺序:停止镜像里的容器,再删除容器,最后再删除镜像 】docker rmi 镜像id# 列出所有的容器 IDdocker ps -aq# 停止所有的容器docker stop $(docker ps -aq)# 删除所有的容器docker rm $(docker ps -aq)# 删除所有的镜像docker rmi $(docker images -q)# 停止并删除容器docker ps -a | grep 容器ID | awk '{print $1}' | xargs -i docker stop {} | xargs -i docker rm {}# 删除镜像# docker images 获取所有images# grep -E "xxxxx" 筛选到特定的images# awk ‘ {print $3}’ 打印第三列 即image id列# uniq 检查及删除文本文件中重复出现的行列# xargs -I {} 多行转单行# docker rmi --force {} 删除所有指定iddocker images | grep -E "xxx" | awk '{print $3}' | uniq | xargs -I {} docker rmi --force {}# ex: 删除镜像 `redis:latest`docker images | grep -E redis | grep latest| awk '{print $3}' | uniq | xargs -I {} docker rmi --force {}# 删除所有停止的容器docker container prune# 删除所有不使用的镜像docker image prune --force --all# 或docker image prune -f -a# 查看容器运行内存信息 【参数`mem_limit: 300m` # 最大使用内存】docker stats nacos_server# CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS# nacos_server 19.18% 264 MiB / 300 MiB 87.99% 172 kB / 99.9 kB 39.4 MB / 127 kB 145# 进入容器docker exec -it 容器ID /bin/bash# 以交互模式启动一个容器,在容器内执行/bin/bash命令docker run -i -t 容器ID /bin/bash# 查看容器日志 -t:显示时间戳docker logs -f -t 容器iddocker logs -fn10 -t 容器id# 登陆镜像仓库docker login# 登录阿里云仓库docker login -u 用户名 -p 密码 registry.cn-hangzhou.aliyuncs.com# 获取镜像docker pull 镜像仓库地址# 上传镜像docker push 镜像仓库地址# 查看镜像的创建历史docker history 镜像仓库地址# 构造镜像# 用法 docker build -t 镜像名称 .docker build -t docker_demo .# 查询mysql容器端口docker inspect mysql | grep IPAddress
六、Docker认证私有仓库
认证
docker login --username=用户名 仓库地址# ex:认证阿里云docker login --username=xxx registry.cn-hangzhou.aliyuncs.com
查看密码
config.json 会记录登录之后的用户名和密码,只是base64加密之后的密码。
# 查看密码cat ~/.docker/config.json# ex:{ "auths": { "ccr.ccs.tencentyun.com": { "auth": "TMAxxx1Ng==" }, "registry.cn-hangzhou.aliyuncs.com": { "auth": "emhxxxnLg==" } }}# 解密echo 'emhxxxnLg==' | base64 --decode# username:password
移除认证凭证
docker logout 仓库地址# 移除阿里云认证docker logout registry.cn-hangzhou.aliyuncs.com
七、Docker基于容器创建一个新的镜像
# -a :提交的镜像作者;# -c :使用Dockerfile指令来创建镜像;# -m :提交时的说明文字;# -p :在commit时,将容器暂停。# 基于容器创建一个新的镜像docker commit -m "This is MySQL Database 5.7 image" -a "zhengqingya" mysql_server_test registry.cn-hangzhou.aliyuncs.com/zhengqing/mysql5.7:latest# pushdocker push registry.cn-hangzhou.aliyuncs.com/zhengqing/mysql5.7:latest
ex: 提交一个centos6.6
# 拉取镜像docker pull centos:6.6docker images# 运行进入docker run -i -t centos:6.6 bashlsmkdir -p /zhengqingya/softcd zhengqingyaecho '测试' > test.txtexit# 查看操作docker ps -adocker diff centos镜像id# 提交镜像docker commit -m "测试提交" -a "zhengqingya" centos镜像id registry.cn-hangzhou.aliyuncs.com/zhengqing/centos:latestdocker push registry.cn-hangzhou.aliyuncs.com/zhengqing/centos:latest# pull自己制作的镜像docker pull registry.cn-hangzhou.aliyuncs.com/zhengqing/centos:latestdocker run -i -t registry.cn-hangzhou.aliyuncs.com/zhengqing/centos:latest bash
ex: 提交redis
# 运行进入docker run --name redis_server -p 6379:6379 -d redis:latest redis-serverlsmkdir -p /zhengqingya/softcd zhengqingyaecho '测试' > test.txtexit# 查看操作docker ps -adocker diff centos镜像id# 提交镜像docker commit -m "测试提交" -a "zhengqingya" centos镜像id registry.cn-hangzhou.aliyuncs.com/zhengqing/redis_test:latestdocker push registry.cn-hangzhou.aliyuncs.com/zhengqing/redis_test:latest# pull自己制作的镜像docker run --name redis_test_server -p 6000:6379 -d registry.cn-hangzhou.aliyuncs.com/zhengqing/redis_test:latest redis-server
ex: 提交jenkins
# 检查容器里文件结构的更改docker diff jenkins# 提交镜像docker commit -m "测试提交jenkins" -a "zhengqingya" jenkins registry.cn-hangzhou.aliyuncs.com/zhengqing/jenkins:v1docker push registry.cn-hangzhou.aliyuncs.com/zhengqing/jenkins:v1# 运行测试docker run -d --name jenkins_test -p 10000:8080 -u root registry.cn-hangzhou.aliyuncs.com/zhengqing/jenkins:v1
八、Docker保存镜像
1、准备一个修改过后的镜像
# 拉取nginx镜像docker pull nginx# 运行docker run --name nginx -d -p 8080:80 nginx# 进入容器docker exec -it nginx /bin/bash# 修改echo '<!DOCTYPE html><html><head><meta charset="utf-8"><title>nginx容器运行中...</title></head><body> <h1> Hello World </h1> <p> If I were you. </p></body></html>' > /usr/share/nginx/html/index.html# 基于容器创建一个新的镜像# -a :提交的镜像作者;# -c :使用Dockerfile指令来创建镜像;# -m :提交时的说明文字;# -p :在commit时,将容器暂停。docker commit -m "This is my nginx image" -a "zhengqingya" nginx my-nginx:v1
2、导出镜像
docker save -o my-nginx.tar my-nginx:v1
3、导入镜像
# 先删除已存在的旧容器docker rm -f nginx# 删除旧镜像docker rmi my-nginx:v1docker rmi nginx# 导入使用 `docker save` 命令导出的镜像docker load -i my-nginx.tar# 查看镜像docker images# 运行docker run --name nginx -d -p 8080:80 my-nginx:v1
九、Docker镜像推送
# 获取镜像docker pull 镜像仓库地址# 登录阿里云仓库docker login -u 用户名 -p 密码 registry.cn-hangzhou.aliyuncs.com# 将本地镜像名 改为 一个新镜像仓库地址docker tag 镜像名 新镜像仓库地址# 推送镜像docker push 新镜像仓库地址# 举例docker pull nginxdocker tag nginx registry.cn-hangzhou.aliyuncs.com/zhengqing/nginx:latestdocker push registry.cn-hangzhou.aliyuncs.com/zhengqing/nginx:latest
十、Docker配置远程连接2375端口
Docker常见端口
2375:未加密的docker socket,远程root无密码访问主机2376:tls加密套接字,很可能这是您的CI服务器4243端口作为https 443端口的修改2377:群集模式套接字,适用于群集管理器,不适用于docker客户端5000:docker注册服务4789和7946:覆盖网络
1、修改宿主机配置文件
法一
vim /lib/systemd/system/docker.service
在 ExecStart 开头的这一行末尾添加 -H tcp://0.0.0.0:2375
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
法二
vim /etc/docker/daemon.json{ "hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]}
法三
vim /etc/default/docker# 加入下面一行DOCKER_OPTS="-H tcp://0.0.0.0:2375"
2、重启docker
systemctl daemon-reload && systemctl restart docker
3、防火墙开放2375端口
firewall-cmd --zone=public --add-port=2375/tcp --permanent
4、通过外网访问测试成功
http://ip地址:2375/version
# 查看docker版本docker -H tcp://www.zhengqingya.com:2375 version# 查看镜像包docker -H tcp://www.zhengqingya.com:2375 images
十一、Docker容器和宿主机文件互传
# 从容器`mysql_master`里面拷文件到宿主机 前:容器文件路径 后:宿主机路径docker cp mysql_master:/tmp/all.sql /tmp/all.sql# 从宿主机拷文件到容器`mysql_slave`里面 前:宿主机文件路径 后:容器路径docker cp /tmp/all.sql mysql_slave:/tmp/all.sql
十二、Docker容器中执行宿主机docker命令
将docker宿主机的docker文件和docker.sock文件挂载到容器中即可
-v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7
# 把docker相关的命令和依赖使用-v挂载到容器docker run -it -d \--restart=always -u root \-v /usr/bin/docker:/usr/bin/docker \-v /var/run/docker.sock:/var/run/docker.sock \-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7 镜像名称-u root #以root的身份去运行镜像(避免在容器中调用Docker命令没有权限)#最好使用docker用户去运行-v /usr/bin/docker:/usr/bin/docker#将宿主机的docker命令挂载到容器中#可以使用which docker命令查看具体位置#或者把挂载的参数改为: -v $(which docker):/usr/bin/docker-v /var/run/docker.sock:/var/run/docker.sock#容器中的进程可以通过它与Docker守护进程进行通信-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7#libltdl.so.7是Docker命令执行所依赖的函数库#容器中library的默认目录是 /usr/lib/x86_64-linux-gnu/#把宿主机的libltdl.so.7 函数库挂载到该目录即可#可以通过whereis libltdl.so.7命令查看具体位置#centos7位置/usr/lib64/libltdl.so.7#ubuntu位置/usr/lib/x86_64-linux-gnu/libltdl.so.7
举例
docker run -d -p 3307:3306 --name docker_test \-v /usr/bin/docker:/usr/bin/docker \-v /var/run/docker.sock:/var/run/docker.sock \-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7 \-e MYSQL_ROOT_PASSWORD=root \registry.cn-hangzhou.aliyuncs.com/zhengqing/mysql:5.7
十三、Docker镜像与容器自动更新之Watchtower
1、自动清除旧镜像
每次更新都会把旧的镜像清理掉, --cleanup 选项可以简写为 -c
docker run -d \ --name watchtower \ --restart unless-stopped \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --cleanup
2、选择性自动更新
ex: 只自动更新nginx 和 redis 容器
docker run -d \ --name watchtower \ --restart unless-stopped \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower -c \ nginx redis
可以建立一个更新列表文件, 然后通过变量的方式去调用这个列表
cd /zhengqingya/soft/docker# ① echo 'small-tools code-api' > watchtower.list# ② docker run -d \ --name watchtower \ --restart unless-stopped \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower -c \ $(cat ~/.watchtower.list)
3、设置自动更新检查频率
默认情况下 Watchtower 每 5 分钟会轮询一次,如果你觉得这个频率太高了可以使用如下选项来控制更新检查的频率,但二者只能选择其一 --interval, -i - 设置更新检测时间间隔,单位为秒。比如每隔 1 个小时检查一次更新
docker run -d \ --name watchtower \ --restart unless-stopped \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower -c \ --interval 3600
--schedule, -s - 设置定时检测更新时间。格式为 6 字段 Cron 表达式,而非传统的 5 个字段。比如每天凌晨 2 点检查一次更新
docker run -d \ --name watchtower \ --restart unless-stopped \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower -c \ --schedule "0 2 * * * *"
4、最终实战命令
docker run -d \ --name watchtower \ --restart unless-stopped \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower -c \ $(cat $PWD/watchtower.list) \ -i 30
十四、解决Docker容器内无法访问外网问题
tips: 由于环境不同,问题的解决方法也自然不同,下面是小编所在环境的解决方式 ^_^
法一:重建网络docker0
sudo service docker stopsudo pkill dockersudo iptables -t nat -Fsudo ifconfig docker0 downsudo brctl delbr docker0sudo service docker start
法二:开启宿主机的ipv4转发功能
# 修改配置echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf# 重启networksystemctl restart network# 查看 (0->标识未开启 1->标识开启)sysctl net.ipv4.ip_forward# net.ipv4.ip_forward = 1# 重启dockersystemctl restart docker
法三:使用--net=host宿主机网络方式启动容器
# 示例docker run --net=host --name ubuntu_bash -i -t ubuntu:latest /bin/bashdocker run --net=host --rm alpine ping -c 5 baidu.com
法四:关闭SELinux
# 查看SELinux状态getenforce# 临时关闭SELinuxsetenforce 0# 永久关闭SELinuxvim /etc/selinux/config# 将 `SELINUX=enforcing` 改成 `SELINUX=disabled`# 重启liunxreboot
法五
参考 https://github.com/coolsnowwolf/lede/issues/1760
# 修改配置echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.confecho "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.confecho "net.bridge.bridge-nf-call-arptables = 1" >> /etc/sysctl.conf# Luci > 网络 > 防火墙 > 转发:接受# Luci > 状态 > 防火墙 > 重启防火墙service docker restart
法六
rm -rf /var/lib/docker/network/*systemctl restart docker
法七:修改DNS客户端解析文件resolv.conf
# 写入Liunx的DNS客户端解析文件resolv.conf里# 114.114.114.114 => 国内移动、电信和联通通用的DNS# 8.8.8.8 => google提供,更适合国外以及访问国外网站的用户使用# echo nameserver 8.8.8.8 > /etc/resolv.confecho nameserver 114.114.114.114 > /etc/resolv.conf# 查看配置cat /etc/resolv.conf# 测试docker run --rm alpine ping -c 5 baidu.com
法八:和网络工程师沟通下是否做了一定限制
# 先运行一个访问外网的程序docker run --rm alpine ping -c 50 baidu.com# 安装tcpdumpyum install tcpdump# 利用tcpdump进行抓包分析tcpdump -i docker0 icmp# 发现有request包,表明本机到baidu的包,baidu是接收到的,可能是百度没响应(可能性不大)或者被公司防火墙阻断了
法九:宿主机防火墙开启伪装IP功能
tips: 感觉无用,小编直接关防火墙也没解决网络问题
# 查看防火墙状态firewall-cmd --state# 查看防火墙是否开启ip地址转发(ip地址伪装)firewall-cmd --query-masquerade# 开启ip地址转发firewall-cmd --add-masquerade --permanent# 将网络接口 docker0 加入 trusted zone,解决 DNS 问题firewall-cmd --permanent --zone=trusted --add-interface=docker0# 更新防火墙规则firewall-cmd --reload
法十:重装docker
此方式乃是最后无奈之举了...
临时测试容器内能够ping
docker run --rm alpine ping -c 5 baidu.com
小编个人问题记录 -- 未解决
基于电信网环境,在局域网window上安装centos7.6系统,宿主机能正常访问外网,但容器内不行,且容器内dns解析有问题; 如果直接访问ip的话,tcpdump抓包docker0发现只有请求,无任何响应。
临时使用--net=host方式解决外网访问问题,还待持续研究!
十五、Dockerfile构建应用镜像
ex: 构建一个java的jar运行
1、Dockerfile
# 拉取jdk基础镜像FROM openjdk:8-jdk-alpine# 维护者信息MAINTAINER zhengqingya# 添加jar包到容器中 -- tips: xx.jar 和 Dockerfile 在同一级ADD app.jar /home/# 对外暴漏的端口号# [注:EXPOSE指令只是声明容器运行时提供的服务端口,给读者看有哪些端口,在运行时只会开启程序自身的端口!!]EXPOSE 80# 运行CMD java -jar /home/app.jar
2、构建镜像
# 构建镜像 -f:指定Dockerfile文件路径 --no-cache:构建镜像时不使用缓存docker build -f Dockerfile -t "registry.cn-hangzhou.aliyuncs.com/zhengqingya/demo:dev" . --no-cache
3、运行
# 运行docker run -d -p 80:80 --name app registry.cn-hangzhou.aliyuncs.com/zhengqingya/demo:dev# 进入容器docker exec -it app /bin/shcd /home
十六、Docker可视化管理工具 -- Portainer
docker run -d -p 9000:9000 --restart=always --name portainer -v /var/run/docker.sock:/var/run/docker.sock registry.cn-hangzhou.aliyuncs.com/zhengqing/portainer:1.24.1
十七、docker-compose
请移步 https://gitee.com/zhengqingya/docker-compose.git 通过docker-compose编排一系列环境进行一键快速部署运行,小白运维神器。
使用举例 -- 部署MySQL5.7
# 环境准备git clone https://gitee.com/zhengqingya/docker-compose.gitcd docker-compose/Liunx# 运行docker-compose -f docker-compose-mysql5.7.yml -p mysql5.7 up -d
今日分享语句: 不要失去信心,只要坚持不懈,就终会有成果的。
版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除