Docker

106 阅读5分钟

Ubuntu Jammy 22.04 (LTS)安装docker

1,设置docker的apt存储库

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

2,安装docker包

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

3,运行

sudo docker run hello-world

centos安装docker

官网:docs.docker.com/engine/inst…

  1. 卸载旧版本
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 配置docker的yum库
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

如果升级到python3版本,需要修改配置

vi /usr/bin/yum-config-manager

image.png

  1. 安装docker
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  1. 启动和校验
# 启动Docker
systemctl start docker
 
# 停止Docker
systemctl stop docker
 
# 重启
systemctl restart docker
 
# 设置开机自启
systemctl enable docker
 
# 执行docker ps命令,如果不报错,说明安装启动成功
docker ps

5.配置镜像加速

image.png

image.png

docker部署mysql

docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e TZ=Asia/Shanghai \
  -e MYSQL_ROOT_PASSWORD=123 \
  mysql

image.png

docker部署redis

1,下载镜像文件
docker pull redis
2,创建实例启动
mkdir -p /mydata/redis/conf
touch /mydata/redis/conf/redis.conf

docker run -p 6379:6379 --name redis -v /mydata/redis/data:/data -v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf -d redis redis-sever /etc/redis/redis.conf
3,进入redis-cli测试
docker exec -it redis redis-cli

docker基础

常见命令

image.png

image.png

docker images -a #列出所有镜像
docker images -q #只列出镜像id
docker rmi -f id #通过id删除镜像
docker rmi -f $(docker images -aq) #删除全部镜像
docker rm -f id #通过id删除容器
docker rm -f $(docker ps -aq)#删除全部容器
docker ps -a #列出所有运行+历史容器
docker ps -n 5 列出最近5个容器
docker ps -q 只显示容器编号
ctrl+p+q #退出不停止容器
docker run -it centos /bin/bash #进入容器

部署nginx

# 第1步,去DockerHub查看nginx镜像仓库及相关信息
 
# 第2步,拉取Nginx镜像
docker pull nginx
 
# 第3步,查看镜像
docker images
# 结果如下:
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        latest    605c77e624dd   16 months ago   141MB
mysql        latest    3218b38490ce   17 months ago   516MB
 
# 第4步,创建并允许Nginx容器
docker run -d --name nginx -p 80:80 nginx
 
# 第5步,查看运行中容器
docker ps
# 也可以加格式化方式访问,格式会更加清爽
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
 
# 第6步,访问网页,地址:http://虚拟机地址
 
# 第7步,停止容器
docker stop nginx
 
# 第8步,查看所有容器
docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
 
# 第9步,再次启动nginx容器
docker start nginx
 
# 第10步,再次查看容器
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
 
# 第11步,查看容器详细信息
docker inspect nginx
 
# 第12步,进入容器,查看容器内目录
docker exec -it nginx /bin/bash
# 或者,可以进入MySQL
docker exec -it mysql mysql -uroot -p
 
# 第13步,删除容器
docker rm nginx
# 发现无法删除,因为容器运行中,强制删除容器
docker rm -f nginx
# 查看路径
whereis nginx

数据卷

数据卷(volume) 是一个虚拟目录,是容器内目录宿主机 目录之间映射的桥梁。

image.png

image.png

利用nginx的html目录挂载

# 1.首先创建容器并指定数据卷,注意通过 -v 参数来指定数据卷
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
 
# 2.然后查看数据卷
docker volume ls
# 结果
DRIVER    VOLUME NAME
local     29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f
local     html
 
# 3.查看数据卷详情
docker volume inspect html
# 结果
[
    {
        "CreatedAt": "2024-05-17T19:57:08+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/html/_data",
        "Name": "html",
        "Options": null,
        "Scope": "local"
    }
]
 
# 4.查看/var/lib/docker/volumes/html/_data目录
ll /var/lib/docker/volumes/html/_data
# 可以看到与nginx的html目录内容一样,结果如下:
总用量 8
-rw-r--r--. 1 root root 497 12月 28 2021 50x.html
-rw-r--r--. 1 root root 615 12月 28 2021 index.html
 
# 5.进入该目录,并随意修改index.html内容
cd /var/lib/docker/volumes/html/_data
vi index.html
 
# 6.打开页面,查看效果
 
# 7.进入容器内部,查看/usr/share/nginx/html目录内的文件是否变化
docker exec -it nginx bash

注意: 你像我们这个例子是指定了挂载目录,如果不指定,自动会为你挂载到/usr/lib下。

image.png

本地目录挂载mysql

# 1.删除原来的MySQL容器
docker rm -f mysql
 
# 2.进入root目录
cd ~
 
# 3.创建并运行新mysql容器,挂载本地目录
docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e TZ=Asia/Shanghai \
  -e MYSQL_ROOT_PASSWORD=123 \
  -v ./mysql/data:/var/lib/mysql \
  -v ./mysql/conf:/etc/mysql/conf.d \
  -v ./mysql/init:/docker-entrypoint-initdb.d \
  mysql
 
# 4.查看root目录,可以发现~/mysql/data目录已经自动创建好了
ls -l mysql
# 结果:
总用量 4
drwxr-xr-x. 2 root    root   20 5月  19 15:11 conf
drwxr-xr-x. 7 polkitd root 4096 5月  19 15:11 data
drwxr-xr-x. 2 root    root   23 5月  19 15:11 init
 
# 查看data目录,会发现里面有大量数据库数据,说明数据库完成了初始化
ls -l data
 
# 5.查看MySQL容器内数据
# 5.1.进入MySQL
docker exec -it mysql mysql -uroot -p123
# 5.2.查看编码表
show variables like "%char%";
# 5.3.结果,发现编码是utf8mb4没有问题
+--------------------------+--------------------------------+
| Variable_name            | Value                          |
+--------------------------+--------------------------------+
| character_set_client     | utf8mb4                        |
| character_set_connection | utf8mb4                        |
| character_set_database   | utf8mb4                        |
| character_set_filesystem | binary                         |
| character_set_results    | utf8mb4                        |
| character_set_server     | utf8mb4                        |
| character_set_system     | utf8mb3                        |
| character_sets_dir       | /usr/share/mysql-8.0/charsets/ |
+--------------------------+--------------------------------+
 
# 6.查看数据
# 6.1.查看数据库
show databases;
# 结果,hmall是黑马商城数据库
+--------------------+
| Database           |
+--------------------+
| hmall              |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)
# 6.2.切换到hmall数据库
use hmall;
# 6.3.查看表
show tables;
# 结果:
+-----------------+
| Tables_in_hmall |
+-----------------+
| address         |
| cart            |
| item            |
| order           |
| order_detail    |
| order_logistics |
| pay_order       |
| user            |
+-----------------+
# 6.4.查看address表数据
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
| id | user_id | province | city   | town     | mobile      | street        | contact   | is_default | notes |
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
| 59 |       1 | 北京     | 北京   | 朝阳区    | 13900112222 | 金燕龙办公楼   | 李佳诚    | 0          | NULL  |
| 60 |       1 | 北京     | 北京   | 朝阳区    | 13700221122 | 修正大厦       | 李佳红    | 0          | NULL  |
| 61 |       1 | 上海     | 上海   | 浦东新区  | 13301212233 | 航头镇航头路   | 李佳星    | 1          | NULL  |
| 63 |       1 | 广东     | 佛山   | 永春      | 13301212233 | 永春武馆       | 李晓龙    | 0          | NULL  |
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
4 rows in set (0.00 sec)

镜像

镜像结构

image.png

DockerFile

image.png

例如,要基于Ubuntu镜像来构建一个Java应用,其Dockerfile内容如下:

# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
ENV TZ=Asia/Shanghai
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 设定时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装JDK
RUN cd $JAVA_DIR \
 && tar -xf ./jdk8.tar.gz \
 && mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 指定项目监听的端口
EXPOSE 8080
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]

就有人提供了基础的系统加JDK环境,我们在此基础上制作java镜像,就可以省去JDK的配置了:

# 基础镜像
FROM openjdk:11.0-jre-buster
# 设定时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]

image.png

image.png

image.png 运行镜像

# 1.创建并运行容器
docker run -d --name dd -p 8090:8090 docker-demo:1.0
# 2.查看容器
dps
# 结果
CONTAINER ID   IMAGE             PORTS                                                  STATUS         NAMES
78a000447b49   docker-demo:1.0   0.0.0.0:8080->8080/tcp, :::8090->8090/tcp              Up 2 seconds   dd
f63cfead8502   mysql             0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   Up 2 hours     mysql
 
# 3.访问
curl localhost:8080/hello/count
# 结果:
<h5>欢迎访问黑马商城, 这是您第1次访问<h5>

网络

上节课我们创建了一个Java项目的容器,而Java项目往往需要访问其它各种中间件,例如MySQL、Redis等。现在,我们的容器之间能否互相访问呢?我们来测试一下:

首先,我们查看下MySQL容器的详细信息,重点关注其中的网络IP地址:

# 1.用基本命令,寻找Networks.bridge.IPAddress属性
docker inspect mysql
# 也可以使用format过滤结果
docker inspect --format='{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' mysql
# 得到IP地址如下:
172.17.0.2
 
# 2.然后通过命令进入dd容器
docker exec -it dd bash
 
# 3.在容器内,通过ping命令测试网络
ping 172.17.0.2
# 结果
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.058 ms

发现可以互联,没有问题。

但是,容器的网络IP其实是一个虚拟的IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个IP,而在部署时很可能MySQL容器的IP会发生变化,连接会失败。

所以,我们必须借助于docker的网络功能来解决这个问题,官方文档: docs.docker.com/engine/refe…

image.png

# 1.首先通过命令创建一个网络
docker network create hmall
 
# 2.然后查看网络
docker network ls
# 结果:
NETWORK ID     NAME      DRIVER    SCOPE
639bc44d0a87   bridge    bridge    local
403f16ec62a2   hmall     bridge    local
0dc0f72a0fbb   host      host      local
cd8d3e8df47b   none      null      local
# 其中,除了hmall以外,其它都是默认的网络
 
# 3.让dd和mysql都加入该网络,注意,在加入网络时可以通过--alias给容器起别名
# 这样该网络内的其它容器可以用别名互相访问!
# 3.1.mysql容器,指定别名为db,另外每一个容器都有一个别名是容器名
docker network connect hmall mysql --alias db
# 3.2.db容器,也就是我们的java项目
docker network connect hmall dd
 
# 4.进入dd容器,尝试利用别名访问db
# 4.1.进入容器
docker exec -it dd bash
# 4.2.用db别名访问
ping db
# 结果
PING db (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.056 ms
# 4.3.用容器名访问
ping mysql
# 结果:
PING mysql (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms

OK,现在无需记住IP地址也可以实现容器互联了。

总结

  • 在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身
  • 在同一个自定义网络中的容器,可以通过别名互相访问

项目部署

Docker部署kafka集群

image.png

  • 创建Zookeeper部署环境目录(三台服务器相同)
sudo mkdir /data/kafka_cluster
cd /data/kafka_cluster
sudo mkdir -p zookeeper/config
sudo mkdir -p zookeeper/data
  • 创建Zookeeper配置文件(三台服务器相同)
sudo vim zookeeper/config/zoo.cfg
# 粘贴下方代码保存退出
clientPort=2181
dataDir=/data
dataLogDir=/data/log
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
4lw.commands.whitelist=*
server.1=192.168.234.131:2888:3888
server.2=192.168.234.132:2888:3888
server.3=192.168.234.133:2888:3888
  • 配置Zookeeper节点ID(三台服务器myid不同)
sudo vim zookeeper/data/myid
# 分别向131,132,133节点写入1,2,3保存退出
  • 启动Zookeeper服务(三台服务器容器命名可以相同)
#启动zookeeper
# 节点1服务器:131
sudo docker run --network host -v /data/kafka_cluster/zookeeper/data:/data -v /data/kafka_cluster/zookeeper/conf/zoo.cfg:/conf/zoo.cfg --name zookeeper-1 -itd zookeeper
# 节点2服务器:132
sudo docker run --network host -v /data/kafka_cluster/zookeeper/data:/data -v /data/kafka_cluster/zookeeper/conf/zoo.cfg:/conf/zoo.cfg --name zookeeper-2 -itd zookeeper
# 节点3服务器:133
sudo docker run --network host -v /data/kafka_cluster/zookeeper/data:/data -v /data/kafka_cluster/zookeeper/conf/zoo.cfg:/conf/zoo.cfg --name zookeeper-3 -itd zookeeper
  • 创建kafka-server部署环境目录(三台服务器相同)
sudo mkdir -p kafka/log
  • 启动Kafka服务(三台服务器不同)
# 节点1服务器:131
sudo docker run -p 9092:9092 --name kafka-1 -itd \
-e KAFKA_BROKER_ID=1 -e KAFKA_ZOOKEEPER_CONNECT=192.168.234.131:2181,192.168.234.132:2181,192.168.234.133:2181 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://192.168.234.131:9092 \
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -v /data/kafka/log:/kafka wurstmeister/kafka
# 节点2服务器:132
sudo docker run -p 9092:9092 --name kafka-2 -itd \
-e KAFKA_BROKER_ID=2 -e KAFKA_ZOOKEEPER_CONNECT=192.168.234.131:2181,192.168.234.132:2181,192.168.234.133:2181 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://192.168.234.132:9092 \
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -v /data/kafka/log:/kafka wurstmeister/kafka
# 节点3服务器:133
sudo docker run -p 9092:9092 --name kafka-3 -itd \
-e KAFKA_BROKER_ID=3 -e KAFKA_ZOOKEEPER_CONNECT=192.168.234.131:2181,192.168.234.132:2181,192.168.234.133:2181 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://192.168.234.133:9092 \
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -v /data/kafka/log:/kafka wurstmeister/kafka
  • 启动Kafka-manager服务(为了便于可视化管理,可只在主节点)
sudo docker run -p 9000:9000 --name kafka-manager -itd \
-e ZK_HOSTS=192.168.234.131:2181,192.168.234.132:2181,192.168.234.133:2181 sheepkiller/kafka-manager
  • 网页端打开主节点的9000端口,如下图所示进行集群的添加,其他设置可暂时不设置;

image.png