Docker 学习
基础
为什么有 Docker

Docker 如何工作
安装的了 docker 环境的服务器叫做 docker 主机,用户通过 docker-cli 发送命令让 docker 主机Docker Daemon 执行 镜像的拉取、运行,容器的运行、构建、分享
pull 拉去镜像到本机
run 运行镜像启动应用成为容器
build 自己打包镜像
push 发布自己的镜像到应用市场


购买云服务器
购买腾讯云按量收费服务器
安装Docker
安装 Centos 版本的

# 移除旧版本docker
sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine# 配置docker yum源。
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 安装 最新 docker
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin# 启动& 开机启动docker; enable + start 二合一
systemctl enable docker --now# 配置加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://82m9ar63.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
Docker 常见命令
#查看运行中的容器
docker ps
#查看所有容器
docker ps -a
#搜索镜像
docker search nginx
#下载镜像
docker pull nginx
#下载指定版本镜像
docker pull nginx:1.26.0
#查看所有镜像
docker images
#删除指定id的镜像
docker rmi e784f4560448#运行一个新容器
docker run nginx
#停止容器
docker stop keen_blackwell
#启动容器
docker start 592
#重启容器
docker restart 592
#查看容器资源占用情况
docker stats 592
#查看容器日志
docker logs 592
#删除指定容器
docker rm 592
#强制删除指定容器
docker rm -f 592
# 后台启动容器
docker run -d --name mynginx nginx
# 后台启动并暴露端口
docker run -d --name mynginx -p 80:80 nginx
# 进入容器内部
docker exec -it mynginx /bin/bash
# 输出内容改变 nginx 默认文件
echo "<h1>Hello,docker.</h1>" > usr/share/nginx/html/index.html# 提交容器变化打成一个新的镜像
docker commit -m "update index.html" mynginx mynginx:v1.0
# 保存镜像为指定文件
docker save -o mynginx.tar mynginx:v1.0
# 删除多个镜像
docker rmi bde7d154a67f 94543a6c1aef e784f4560448
# 加载镜像
docker load -i mynginx.tar # 登录 docker hub
docker login
# 重新给镜像打标签
docker tag mynginx:v1.0 leifengyang/mynginx:v1.0
# 推送镜像
docker push leifengyang/mynginx:v1.0
可以充分利用 help 文档查看命令帮助 比如
docker ps --help
docker tag --help
run 细节
直接 docker run 容器 ,会阻塞启动,关闭窗口容器就停止
-d 后台启动
-- name 命名
-p 服务器端口:容器端口 端口映射
# $() 返回里面命令的结果,拼接使用命令
docker rm -f $(docker ps -aq)
目录挂载
两种方式,注意区分:
- 目录挂载:
-v /app/nghtml:/usr/share/nginx/html
初始化以左边目录为准,左边目录为空没有那么容器内对于目录也会为空,修改两边都会同步 - 卷映射:
-v ngconf:/etc/nginx
初始化以右边目录为准,右边目录的文件和文件夹两边同步,卷是相当于一个盘,默认目录在/var/lib/docker/volumes/

docker run -d -p 99:80 \
-v /app/nghtml:/usr/share/nginx/html \
-v ngconf:/etc/nginx \
--name app03 \
nginx
Docker 网络
掌握 docker 网络机制,轻松构建集群
容器内访问同台服务器内的容器该怎么做
容器内创建了两个容器,看到可以直接通过 curl 访问另一台,但是这访问在公网绕一大圈回来,效率不高
[root@VM-0-10-centos _data]# docker run -d -p 88:80 --name app1 5ef79149e0ec
8b4f0f33eb0278bf7ed73e7b3a66942dd0a79a768973c85ce43f60e48077851f
[root@VM-0-10-centos _data]# docker run -d -p 99:80 --name app2 5ef79149e0ec
d9c2640a62e5408a5e0a8d7c1741e6857ad376ce0c26d46492ffa9c94f740fcd
[root@VM-0-10-centos _data]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d9c2640a62e5 5ef79149e0ec "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:99->80/tcp, :::99->80/tcp app2
8b4f0f33eb02 5ef79149e0ec "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:88->80/tcp, :::88->80/tcp app1
[root@VM-0-10-centos _data]# docker exec -it d9c2640a62e5 bash
root@d9c2640a62e5:/# curl http://119.45.203.117:88/
<!DOCTYPE html>
<html>
<head>
docker 一个默认机制,每一个应用启动时都会加入一个docker 的默认网络 叫 docker0
ip a 可以看到所有网卡信息

docker container inspect 查看容器细节在 Networks 中 docker0 作为网关地址

所以在容器内部访问其他容器,可以通过访问容器的 IPAddress 加端口curl http://172.17.0.3:80,但是容器的 ip 可能会发生变化,需要一个稳定的访问方式,就是通过自定义 docker 内部域名。
创建自定义网络,容器名就是稳定域名

启动时加入网络,容器内就可用容器名作为域名,在容器之间访问
docker run -d -p 88:80 --name app1 --network mynet mynginx:v1.0docker run -d -p 99:80 --name app2 --network mynet mynginx:v1.0
[root@VM-0-10-centos ~]# docker exec -it app1 bash
root@f93b1d532376:/# curl http://app2
redis主从同步集群

启动 bitnami 的 redis 镜像,主要是这个镜像提前改好了集群要用到的配置
#自定义网络
docker network create mynet
#主节点
docker run -d -p 6379:6379 \
-v /app/rd1:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=master \
-e REDIS_PASSWORD=123456 \
--network mynet --name redis01 \
bitnami/redis#从节点
docker run -d -p 6380:6379 \
-v /app/rd2:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=slave \
-e REDIS_MASTER_HOST=redis01 \
-e REDIS_MASTER_PORT_NUMBER=6379 \
-e REDIS_MASTER_PASSWORD=123456 \
-e REDIS_PASSWORD=123456 \
--network mynet --name redis02 \
bitnami/redis
这是同一台服务器内的容器实验,正常生产环境下是两台服务器。只要在启动的REDIS_MASTER_HOST 中,将参数改为公网 IP 或者云服务器提供的内网 IP 就可以
Docker compose
docker 用来批量管理容器的工具

实验
正常启动一个博客系统和 MySQL
#创建网络
docker network create blog#启动mysql
docker run -d -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=wordpress \
-v mysql-data:/var/lib/mysql \
-v /app/myconf:/etc/mysql/conf.d \
--restart always --name mysql \
--network blog \
mysql:8.0#启动wordpress
docker run -d -p 8080:80 \
-e WORDPRESS_DB_HOST=mysql \
-e WORDPRESS_DB_USER=root \
-e WORDPRESS_DB_PASSWORD=123456 \
-e WORDPRESS_DB_NAME=wordpress \
-v wordpress:/var/www/html \
--restart always --name wordpress-app \
--network blog \
wordpress:latest
使用 docker compose 文件启动这两个容器,按照官方文档,将需要的配置参数依次写入文件就行
name: myblog
services:mysql:container_name: mysqlimage: mysql:8.0ports:- "3306:3306"environment:- MYSQL_ROOT_PASSWORD=123456- MYSQL_DATABASE=wordpressvolumes:- mysql-data:/var/lib/mysql- /app/myconf:/etc/mysql/conf.drestart: alwaysnetworks:- blogwordpress:image: wordpressports:- "8080:80"environment:WORDPRESS_DB_HOST: mysqlWORDPRESS_DB_USER: rootWORDPRESS_DB_PASSWORD: 123456WORDPRESS_DB_NAME: wordpressvolumes:- wordpress:/var/www/htmlrestart: alwaysnetworks:- blogdepends_on:- mysqlvolumes:mysql-data:wordpress:networks:blog:
docker compose -f compose.yml up -d
- 增量更新
- 修改 Docker Compose 文件。重新启动应用。只会触发修改项的重新启动。
- 数据不删
- 默认就算down了容器,所有挂载的卷不会被移除。比较安全
Dockerfile
制作镜像

FROM openjdk:17LABEL author=leifengyangCOPY app.jar /app.jarEXPOSE 8080ENTRYPOINT ["java","-jar","/app.jar"]
上传 app.jar 构建 Dockerfile 文件
docker build -f Dockerfile -t myjavaapp:v1.0 .

docker run -d -p 8888:8080 myjavaapp:v1.0
就可启动制作好的镜像
Docker 镜像分层存储机制
类似于 git 基于初始镜像,记录他的改变,

同一个应用不同的镜像,镜像只存储了他增量的部分,相同的地方直接共用

查看官方 nginx 镜像和自己构建的 mynginx镜像,只有最上的一处改变,而相同的地方直接共用

docker image inspect mynginx:v1.0
容器细节命令也能看出构建区别

一个镜像启动容器后的存储结构示意图,镜像层只读。容器按照镜像启动,并对镜像有所修改,那么修改的部分存储在单独一层可读可写,容器将所有的修改存储在这一层,所以容器删除后所有数据丢失


docker ps -s可以查看镜像层和虚拟层的分别占用

结束语

