2023-11-01 10:31:16 +08:00

543 lines
18 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Docker
date: 2021-03-23 10:30:31
author: 文永达
top_img: https://gcore.jsdelivr.net/gh/volantis-x/cdn-wallpaper/abstract/67239FBB-E15D-4F4F-8EE8-0F1C9F3C4E7C.jpeg
---
# Docker 简介
---
Docker海豚身上背着一堆集装箱
场景:
传统的服务器 Docker
1G左右 几十兆几百兆
CentOS占CPU Docker CPU引擎占用低
1-2分钟 几秒
安装软件 安装方便
部署应用 部署应用,挂载,数据卷
多个应用放到一起 每个应用服务都是一个容器,相互隔离
一个独立的操作系统 必须依赖于操作系统推荐使用Linux
# Docker 安装
```shell
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
# 另一种方式
curl -sSL https://get.daocloud.io/docker | sh
# 如上述两种方式都不行
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 查看所有可安装版本
yum list docker-ce --showduplicates | sort -r
# 安装
yum install docker-ce-18.03.1.ce
# almalinux centos8
# 添加必要的Docker存储库
dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
# 找到Docker CE的可安装版本
dnf list docker-ce --showduplicates | sort -r
# 安装Docker CE
dnf install docker-ce-3:24.0.7-1.el9
```
1、镜像image。一个镜像代表一个软件。如redis镜像mysql镜像tomcat镜像。。
特点:只读
2、容器container。一个镜像只要一启动称之为启动了一个容器。
3、仓库repository。存储docker中的镜像具体位置
远程仓库:在全球范围内有一个远程仓库
本地仓库:当前自己机器中下载的镜像存储位置
Docker配置阿里云镜像加速
https://www.cnblogs.com/LUA123/p/11401962.html
# Docker 使用
## 查看 Docker 信息
```shell
docker info
```
## 查看 Docker 镜像 image
```shell
docker images
```
## Docker 安装镜像 image
MySQL 5.7
```shell
docker pull mysql:5.7
```
## Docker 移除镜像 image
若已有镜像用于容器,请先将容器删除
```shell
docker rm -f <CONTAINER ID>
```
```shell
docker image rm hello-world
docker rmi hello-world
```
```shell
# 第一个8080是外部海豚上的 第二个8080是内部集装箱上的
docker run -p 8080:8080
```
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-d: 后台运行容器,并返回容器 ID
-i: 以交互模式运行容器,通常与 -t 同时使用;
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-p: 指定端口映射,格式为:主机 (宿主) 端口:容器端口
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
--name="nginx-lb": 为容器指定一个名称;
--dns 8.8.8.8: 指定容器使用的 DNS 服务器,默认和宿主一致;
--dns-search example.com: 指定容器 DNS 搜索域名,默认和宿主一致;
-h "mars": 指定容器的 hostname
-e username="ritchie": 设置环境变量;
--env-file=[]: 从指定文件读入环境变量;
--cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定 CPU 运行;
-m : 设置容器使用内存最大值;
--net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
--link=[]: 添加链接到另一个容器;
--expose=[]: 开放一个端口或一组端口;
--volume , -v 绑定一个卷
docker启动容器
```shell
docker start <container id>
```
docker停止容器
```shell
docker stop <container id>
```
docker重启容器
```shell
docker restart <container id>
```
## Docker 容器与宿主机时间不同步
对于已创建的容器:
```shell
docker cp /usr/share/zoneinfo/Asia/Shanghai <containername>:/etc/localtime
```
创建容器前
```shell
docker run -d -p 8080:80 -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone <containername>
```
## 修改运行中的 Docker 容器的端口映射和挂载目录
方法一:删除原有容器,重建新容器
参考以上移除容器,启动容器
方法二修改配置文件重启docker服务
容器配置文件路径:
/var/lib/docker/containers/[[hash_of_the_container]/hostconfig.json]
其中的hashofthecontainer是docker镜像的hash值可以通过docker ps或者docker inspect containername查看。CONTAINER ID就可以看出来
可以到/var/lib/docker/containers目录下ls -l
```json
{"Binds":["/usr/docker/redis/redis-slave2.conf:/usr/local/etc/redis/redis.conf"],"ContainerIDFile":"","LogConfig":{"Type":"json-file","Config":{}},"NetworkMode":"default","PortBindings":{"6379/tcp":[{"HostIp":"","HostPort":"6381"}]},"RestartPolicy":{"Name":"no","MaximumRetryCount":0},"AutoRemove":false,"VolumeDriver":"","VolumesFrom":null,"CapAdd":null,"CapDrop":null,"Dns":[],"DnsOptions":[],"DnsSearch":[],"ExtraHosts":null,"GroupAdd":null,"IpcMode":"shareable","Cgroup":"","Links":null,"OomScoreAdj":0,"PidMode":"","Privileged":false,"PublishAllPorts":false,"ReadonlyRootfs":false,"SecurityOpt":null,"UTSMode":"","UsernsMode":"","ShmSize":67108864,"Runtime":"runc","ConsoleSize":[0,0],"Isolation":"","CpuShares":0,"Memory":0,"NanoCpus":0,"CgroupParent":"","BlkioWeight":0,"BlkioWeightDevice":[],"BlkioDeviceReadBps":null,"BlkioDeviceWriteBps":null,"BlkioDeviceReadIOps":null,"BlkioDeviceWriteIOps":null,"CpuPeriod":0,"CpuQuota":0,"CpuRealtimePeriod":0,"CpuRealtimeRuntime":0,"CpusetCpus":"","CpusetMems":"","Devices":[],"DeviceCgroupRules":null,"DiskQuota":0,"KernelMemory":0,"MemoryReservation":0,"MemorySwap":0,"MemorySwappiness":null,"OomKillDisable":false,"PidsLimit":0,"Ulimits":null,"CpuCount":0,"CpuPercent":0,"IOMaximumIOps":0,"IOMaximumBandwidth":0}
```
重启docker服务再启动容器服务就可以了。
```shell
systemctl restart docker
docker ps -a
docker start <container id>
```
## Docker 的镜像迁移到另一台服务器
```shell
# 找到想要移动的docker容器ID
dockerCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58ac9237b040 redis:4.0.11 "docker-entrypoint.s…" 5 hours ago Up 2 hours 0.0.0.0:6380->6379/tcp redis-slave1
454bb484f90a redis:4.0.11 "docker-entrypoint.s…" 5 hours ago Up 2 hours 0.0.0.0:6379->6379/tcp redis-master
ps -a
# 提交变更并且把容器保存成镜像命名为redis-master
docker commit 454bb484f90a redis-master
# 把redis-master镜像保存成tar文件
docker save redis-master > /root/mysoftware/docker-file/redis/redis-master.tar
# 拷贝到新的机器执行load命令
docker load < ./redis-master.tar
```
## Docker中 `<none>`镜像的来历及快速删除操作
```shell
docker rmi -f $(docker images | grep "none" | awk '{print $3}')
```
来历在docker反复build一个Dockerfile并且使用相同tag或者不用tag)会存留很多none镜像。第一次build生成一个image id, 再次build后会重新生成一个image id, 命名和上一个一样所以上一个镜像的tag和名字就会自动变成 `<none>`
## Docker Dockerfile
### 什么是 Dockerfile?
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
### 使用 Dockerfile 定制镜像
1. 定制一个 nginx 镜像(构建好的镜像内会有一个 /usr/share/nginx/html/index.html 文件)
在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容:
```dockerfile
FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html
```
2. FROM 和 RUN 指令的作用
**FROM**: 定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。
**RUN**: 用于执行后面跟着的命令行命令。有以下俩种格式:
shell 格式:
```dockerfile
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。
```
exec 格式:
```dockerfile
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
```
**注意**: Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:
```dockerfile
FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
```
以上执行会创建 3 层镜像。可简化为以下格式:
```dockerfile
FROM centos
RUN yum -y install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz
```
如上,以 **&&** 符号连接命令,这样执行后,只会创建 1 层镜像。
### 开始构建镜像
在 Dockerfile 文件的存放目录下,执行构建动作。
以下示例,通过目录下的 Dockerfile 构建一个 nginx:v3镜像名称:镜像标签)。
**注**: 最后的`.`代表本次执行的上下文路径,下一节会介绍。
```shell
docker build -t nginx:v3 .
```
![img](E:\source\repos\XiaodaBlogSource\source\_posts\Docker\dockerfile2.png)
### 上下文路径
上一节中,有提到指令最后一个 **.** 是上下文路径,那么什么是上下文路径呢?
```shell
docker build -t nginx:v3 .
```
上下文路径,是指 docker 在构建镜像有时候想要使用到本机的文件比如复制docker build 命令得知这个路径后,会将路径下的所有内容打包。
**解析**:由于 docker 的运行模式是 C/S。我们本机是 Cdocker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。
如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。
**注意**:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。
### 指令详解
| Dockerfile 指令 | 说明 |
| --------------- | ------------------------------------------------------------ |
| FROM | 指定基础镜像,用于后续的指令构建。 |
| MAINTAINER | 指定Dockerfile的作者/维护者。已启用推荐使用LABEL指令 |
| LABEL | 添加镜像的元数据,使用键值对的形式。 |
| RUN | 在构建过程中在镜像中执行命令。 |
| CMD | 指定容器创建时的默认命令。(可以被覆盖) |
| ENTRYPOINT | 设置容器创建时的主要命令。(不可被覆盖) |
| EXPOSE | 声明容器运行时监听的特定网络端口。 |
| ENV | 在容器内部设置环境变量。 |
| ADD | 将文件、目录或远程URL复制到镜像中。 |
| COPY | 将文件或目录复制到镜像中。 |
| VOLUME | 为容器创建挂载点或声明卷。 |
| WORKDIR | 设置后续指令的工作目录。 |
| USER | 指定后续指令的用户上下文。 |
| ARG | 定义在构建过程中传递给构建器的变量,可使用"docker build"命令设置。 |
| ONBUILD | 当该镜像被用作另一个构建过程的基础时,添加触发器。 |
| STOPSIGNAL | 设置发送给容器以退出的系统调用信号。 |
| HEALTHCHECK | 定义周期性检查容器健康状态的命令。 |
| SHELL | 覆盖Docker中默认的shell用于RUN、CMD和ENTRYPOINT。 |
#### COPY
复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
格式:
```dockerfile
COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
```
**[--chown=<user>:<group>]**:可选参数,用户改变复制到容器内文件的拥有者和属组。
**<源路径>**:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:
```dockerfile
COPY hom* /mydir/
COPY hom?.txt /mydir/
```
**<目标路径>**:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。
# Docker 实例
## Docker 启动 MariaDB
拉取mariadb镜像
```shell
docker pull mariadb:10.2
docker images
docker run --name mariadb10.2 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mariadb:10.2
```
## Docker Redis 主从复制集群搭建
拉取redis4.0.11镜像
```shell
docker pull redis:4.0.11
```
编辑redis.conf
redis-master.conf
```shell
vim /root/mysoftware/docker-file/redis/redis-master.conf
bind 0.0.0.0 #让redis可以被任意ip访问
daemonize yes #让redis服务后台运行
# 如需设定密码
requirepass masterpassword # 设定密码
```
redis-slave1.conf
```shell
vim /root/mysoftware/docker-file/redis/redis-slave1
bind 0.0.0.0 #让redis可以被任意ip访问
daemonize yes #让redis服务后台运行
# 如需设定密码
requirepass masterpassword # 设定密码
# 设置主机地址端口 redis5.0以上为 replicaof <master-IP> <master-port>
slaveof <master-IP> <master-port>
# 查看master ip
docker inspect <container id>
# 主库有密码必需要配置,<master-password>代表主库的访问密码
masterauth <master-password>
```
运行redis容器
redis-master
```shell
# 运行服务
docker run -it --name redis-master -v /usr/docker/redis/redis-master.conf:/usr/etc/redis/redis.conf -v /usr/docker/redis/data/:/data -d -p 35379:6379 redis:4.0.11 /bin/bash
# 进入容器
docker exec -it redis-master bash
# 加载配置
redis-server /usr/local/etc/redis/redis.conf
# 如报错
mkdir -p /usr/redis/bin
# 测试连接
redis-cli -a <master-password>
```
redis-slave1
```shell
# 运行服务
docker run -it --name redis-slave1 -v /usr/docker/redis/redis-slave1.conf:/usr/etc/redis/redis.conf -v /usr/docker/redis/data/:/data -d -p 35380:6379 redis:4.0.11 /bin/bash
# 进入容器
docker exec -it redis-slave1 bash
# 加载配置
redis-server /usr/local/etc/redis/redis.conf
# 如报错 Can't chdir to '/usr/redis/bin': No such file or directory
mkdir -p /usr/redis/bin
# 测试连接
redis-cli
# 查看主从信息
info Replication
# 密码认证
auth <slave-password>
```
## Docker Redis 哨兵高可用集群搭建
## Docker 安装 code-server
```shell
# 拉取镜像
docker pull codercom/code-server
# 创建宿主机目录
mkdir /usr/docker/codeserver
# 创建配置文件
vim /usr/docker/codeserver/config.yaml
bind-addr: 127.0.0.1:8080
auth: password
password: 123456
cert: false
# 创建并启动容器 # -u 表示以 root用户运行
docker run -d -u root -p 8088:8080 --name code-server -v /usr/docker/codeserver/config.yaml:/root/.config/code-server/config.yaml -v /usr/docker/codeserver:/home/code codercom/code-server
```
## Docker 安装 Jenkins
搜索Jenkins镜像
```shell
docker search jenkins
```
![image-20221121125608385](https://markdownhexo.oss-cn-hangzhou.aliyuncs.com/img/image-20221121125608385.png)
拉取镜像
```shell
docker pull jenkins/jenkins
```
查看镜像
```shell
docker images
```
![image-20221121131216876](https://markdownhexo.oss-cn-hangzhou.aliyuncs.com/img/image-20221121131216876.png)
启动镜像
```shell
cd /usr/local
mkdir jenkins_home
docker run -d -uroot -p 8889:8080 -p 50000:50000 --name jenkins -v /usr/bin/docker:/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock -v /etc/sysconfig/docker:/etc/sysconfig/docker -v /usr/local/jenkins_home:/var/jenkins_home -v /etc/localtime:/etc/localtime jenkins/jenkins
```
启动后查看日志
```shell
docker logs jenkins
```
![image-20221121131635658](https://markdownhexo.oss-cn-hangzhou.aliyuncs.com/img/image-20221121131635658.png)可以找到初始密码
## Docker 安装 Nginx
```shell
docker pull nginx
docker run -d \
-p 80:80 \
-p 443:443 \
--name nginx \
--privileged=true \
--restart=always \
-v /usr/local/docker/nginx/html:/usr/share/nginx/html \
-v /usr/local/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /usr/local/docker/nginx/conf/conf.d:/etc/nginx/conf.d \
-v /usr/local/docker/nginx/logs:/var/log/nginx nginx:1.25.2
ps aux | grep "nginx: worker process" | awk '{print $1}'
```
## Docker 安装 SQL Server
```shell
mkdir /etc/sqlserver_data
chmod -R 777 /etc/sqlserver_data
docker pull mcr.microsoft.com/mssql/server
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=Wyd210213" -p 1433:1433 --memory 2000M --name sqlserver2022 -v /etc/sqlserver_data:/var/opt/mssql -d mcr.microsoft.com/mssql/server
```
## Docker 安装 PostgreSQL
```shell
docker pull postgres:latest
docker run -d --name=pgsql -p 5432:5432 -e POSTGRES_PASSWORD=Wyd210213 postgres:latest
```
## Docker 安装 MySQL 8
```shell
docker run \
-p 3306:3306 \
--name mysql \
--restart=always \
-v /usr/local/docker/mysql/mysql-files:/var/lib/mysql-files \
-v /usr/local/docker/mysql/conf:/etc/mysql \
-v /usr/local/docker/mysql/logs:/var/log/mysql \
-v /usr/local/docker/mysql/data:/var/lib/mysql \
-v /etc/localtime:/etc/localtime \
-e MYSQL_ROOT_PASSWORD=Wyd210213 \
-e TZ=Asia/Shanghai \
-d mysql:8.0.21 \
--lower_case_table_names=1
```
## Docker 安装 Redis 7
```shell
# 首先得需要redis.conf否则会映射成文件夹
docker run --restart=always \
-p 6379:6379 \
--name redis \
-v /usr/local/docker/redis/redis.conf:/etc/redis/redis.conf \
-v /usr/local/docker/redis/data:/data \
-v /etc/localtime:/etc/localtime \
-d redis:7.0.13 redis-server /etc/redis/redis.conf
```