docker
- 容器类似轻量级的虚拟机
- 容器共享操作系统的内核
- 容器拥有自己的文件系统、cpu、内存、进程空间等资源
- 容器间相互隔离
- 每个容器都可以看作是一个简易虚拟机
- 官方文档:https://docs.docker.com/manuals/
- 官方社区:https://hub.docker.com/
docker安装
此处以centos为例,其他操作系统和安装方式参考官方文档
- 卸载旧版本
sudo dnf 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 dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- 启动并设置开机启动docker
sudo systemctl enable --now docker
- 检验docker是否安装成功
sudo docker ps #该命令可以查看当前运行的容器
- 配置docker下载镜像地址为腾讯云
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://docker.m.daocloud.io"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
常用docker命令
镜像相关
- 搜索镜像
docker search nginx
- 下载镜像
docker pull nginx[:版本名称]
- 这里如果不指定版本名称则默认下载最新版本
- 要下载指定版本的镜像可以去dockerhub查找
- 查看所有镜像
docker images
- 删除指定id的镜像
docker rmi 镜像ID
容器相关
- 查看运行中的容器
docker ps [-a]
- 参数
-a
可以查看所有容器,包括未运行的
- 运行一个新容器
docker run [-d] [--name 别名] [-p 端口映射] 容器名/容器id
-d
可以让容器后台启动--name
为该容器起一个别名-p
指定物理机与docker之间接口映射- 例如
80:80
,将物理机80端口(外部端口)映射到容器的80端口(内部端口) - 注意,在docker中的各个容器使用的内部端口是容器自身的,故不同容器间可以有重复的内部端口(如容器A使用80端口,容器B也可以使用80端口,但是设置端口映射时外部端口必须唯一)
- 例如
- 进入容器内部
docker exec -it 容器名/容器id /bin/bash
-it
表示以交互模式进入/bin/bash
表示以控制台进入
- 停止容器
docker stop 容器名/容器id
- 启动容器
docker start 容器名/容器id
- 重启容器
docker restart 容器名/容器id
- 查看容器资源占用情况
docker stats 容器名/容器id
- 查看容器日志
docker logs 容器名/容器id
- 删除指定容器
docker rm [-f] 容器名/容器id
- 通常情况下删除容器需要先停止该容器
-f
参数可以不停止,强制删除
持久化相关
- 提交容器变化打包成一个新的镜像
docker commit [-m "提交信息"] 容器名 镜像:版本号
-m
参数可以为此次打包添加自定义信息
- 保存镜像为指定文件
docker save [-o 镜像文件名] 镜像:版本号
-o
参数可以指定生成的文件名称- 这里是将镜像打包成一个tar包(压缩包)以便于传输
- 删除多个镜像
docker rmi 镜像id [镜像id ...]
- 加载镜像
docker load -i 镜像文件名
社区分享相关
- 登录 docker hub
docker login
- 重新给镜像打标签
docker tag 原镜像名 新镜像名
- dockerhub上的镜像通常以
用户名/镜像名:版本名
进行命名
- 推送镜像
docker push 镜像名
docker存储
这里为了方便理解,我们可以将目录挂载看作是软连接,即目录挂载是通过类似"快捷方式"来引用宿主机上的目录/文件;同样的卷映射可以看作是硬链接,即卷映射是将容器内的目录/文件"拷贝"了一份放到卷中,并且docker会保证容器内数据与卷中数据一致
目录挂载
- 为了方便管理容器中应用的数据和配置,可以使用目录挂载来指定一个目录,将该目录作为目标容器中的某一个目录。
- 当容器重新部署,容器内的数据也不会丢失(数据在被挂载的目录中)
- 宿主机和容器之间的文件修改会实时同步。
- 通常使用在开发环境
docker run -v /宿主机路径:/容器路径 镜像名称
# 1假定已经在/app/mynginxhtml下创建了一个index.html文件作为欢迎页
# 2创建一个容器
# 后台启动,端口映射为80到80,别名为mynginx
# 此处的/usr/share/nginx/html目录是容器中nginx存放欢迎页的目录
docker run -d -p 80:80 -v /app/mynginxhtml:/usr/share/nginx/html --name mynginx nginx
# 3删除上面创建的容器
docker rm -f mynginx
# 4重起一个容器,但是挂载同一目录
docker run -d -p 80:80 -v /app/mynginxhtml:/usr/share/nginx/html --name mynginx nginx
# 此时,前一个容器和后一个容器会有相同的欢迎页(数据被保存了)
卷映射
-
使用目录挂载配置文件时,可能会出现配置文件不存在的情况(没有事先将配置文件存放到指定目录下),此时需要使用到卷映射。
-
使用卷映射时docker会在宿主机的特定位置(通常是 /var/lib/docker/volumes/)创建一个卷,并将其挂载到容器中
-
卷的生命周期独立于容器,不会由于容器的删除而删除
-
通常使用在需要持久化的生产环境
-
docker run -v 卷名称:/容器路径 镜像名称
- 创建一个新容器,并开启卷映射
- 使用该命令若卷不存在docker会自动创建一个卷
-
docker volume ls
- 查看docker中存在的卷
-
docker volume create 卷名
- 创建一个新卷
-
docker volume inspect 卷名
- 查看指定卷的详情
# 创建一个卷名为nginxconfig的卷并映射到容器的/etc/nginx目录
docker run -v nginxconfig:/etc/nginx --name mynginxconfig nginx
# 切换到卷目录下,这里之间在特定位置后面加卷名
# 此时会发现一个_data目录,里面存放了容器中/etc/nginx目录中的全部内容
cd /var/lib/docker/volumes/nginxconfig
docker网络
容器间通信
- 通过物理机ip和端口进行通信
- 此种通信方式是由发起方先向物理机发起请求,再从物理机访问到目标容器
# 创建2个容器应用
docker run -d -p 81:80 --name nginx1 nginx
docker run -d -p 82:80 --name nginx2 nginx
# 进入nginx1通过物理机ip(192.168.0.2)和端口访问nginx2
docker exec -it nginx1 bash
curl http://192.168.0.2:82
- 通过容器内部网络ip和端口进行通信
- 默认情况下docker会创建一个bridge网络
- 当创建容器时,docker会将该容器加入此网络
- 在该模式下,每个容器会分配一个独立的网络命名空间,并通过虚拟网桥docker0连接到主机网络
# 创建2个容器应用
docker run -d -p 81:80 --name nginx1 nginx
docker run -d -p 82:80 --name nginx2 nginx
# 获取目标容器ip
docker container inspect nginx2
# 进入nginx1通过内部网络访问nginx2(假设内部ip为172.17.0.2)
docker exec -it nginx1 bash
curl http://172.17.0.2:80
- 通过自定义网络使用容器名进行通信
- 默认情况下(即docker0)不支持使用主机域名来访问不同容器
- 我们需要创建一个自定义网络,将容器名设置为主机域名来进行访问
# 创建自定义网络
docker network create mynet
# 创建2个容器应用
# 这里的--network用于指定要加入的网络,不指定则会默认加入nginx0网络
# 同时会将容器名作为该容器主机的域名
docker run -d -p 81:80 --name nginx1 --network mynet nginx
docker run -d -p 82:80 --name nginx2 --network mynet nginx
# 通过域名访问目标容器应用
docker exec -it nginx1 bash
curl http://nginx2:80
创建单机的docker-redis集群
这里使用了docker compose,下一节会介绍
- 创建docker-compose.yml文件
# 指定版本号
version: '3.8'
services:
# 配置主服务器
redis-master:
#指定镜像为最新镜像
image: redis:latest
#设置主服务器名
container_name: redis-master
#设置端口映射
ports:
- "6379:6379"
#设置目录挂载
volumes:
- ./redis-master-data:/data
#启动redis服务器并启用AOF持久化
command: redis-server --appendonly yes
# 配置从服务器
redis-slave:
image: redis:latest
container_name: redis-slave
ports:
- "6380:6379"
volumes:
- ./redis-slave-data:/data
# 启动redis服务并配置为redis-master的从节点
command: redis-server --appendonly yes --slaveof redis-master 6379
#指定在redis-master启动后才启动
depends_on:
- redis-master
- 启动redis集群
# 在docker-compose.yml文件目录中运行
docker compose -f docker-compose.yaml up -d
docker compose
官方文档非常详尽,可直接访问https://docs.docker.com/reference/compose-file/
使用docker compose创建一个wordpress博客
wordpress-compose.yaml
name: myblog
services:
mysql:
container_name: mysql
image: mysql:8.0
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD: 123456
- MYSQL_DATABASE: wordpress
volumes:
- mysql-data:/var/lib/mysql
- /ap/myconf:/etc/mysql/conf.d
restart: always
networks:
- blog
wordpress:
image: wordpress
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: 123456
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress:/var/www/html
restart: always
networks:
- blog
depends_on:
- mysql
volumes:
mysql-data:
wordpress:
networks:
blog:
- 启动容器
docker compose -f wordpress-compose.yaml up -d
- 若是使用该配置文件重新启动容器,docker会先判断yaml文件是否有修改,若其中某个容器发生了修改,则会重启发生修改了的。
- 关闭容器
docker compose -f wordpress-compose.yaml down [--rmi local|all] [-v]
- 该命令不会移除容器所占用的卷,在下次启动时同样也会引用这些卷
--rmi
- 用以删除镜像
- local选项用以删除没有自定义标签的镜像
- all选项用以删除所有镜像
-v
- 用以删除在该yaml文件中申明的卷
dockerfile自定义镜像
常见指令
- FROM
- 指定镜像基础环境
- RUN
- 运行自定义命令
- CMD
- 容器启动命令或参数
- LABEL
- 自定义标签
- EXPOSE
- 指定暴露端口
- ENV
- 环境变量
- ADD
- 添加文件到镜像
- COPY
- 复制文件到镜像
- ENTRYPOINT
- 容器固定启动命令
- VOLUME
- 数据卷
- USER
- 指定用户和用户组
- WORKDIR
- 指定默认工作目录
- AGR
- 指定构建参数
自定义java镜像
- 将java程序打包成jar包(假定为app.jar),并上传到服务器
- 使用vim命令创建一个dockerfile文件
FROM openjdk:17
LABEL hello word
EXPOSE 8080
COPY app.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
- 构建镜像
docker build -f dockerfile -t helloword:v1.0 ./
- 这里的
-f
用于指定dockerfile文件 -t
用于给该镜像添加tag./
用于指定执行的上下文目录,这里是在dockerfile文件所在目录执行的所以为当前目录