1. Docker 的安装 1.1 安装 Docker 我使用的是 Ubuntu 20.04,安装 Docker 的步骤如下:
1.1.1 更新 apt 包索引。
1.1.2 安装 apt 依赖包,⽤于通过 HTTPS 来获取仓库 1 sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
1.1.3 添加 Docker 的官⽅ GPG 密钥 1 2 curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
1.1.4 通过搜索指纹的后 8 个字符,验证您现在是否拥有带有指纹的密钥 1 sudo apt-key fingerprint 0EBFCD88
输出如下表示成功了:
1 2 3 4 pub rsa4096 2017-02-22 [SCEA] 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 uid [ unknown] Docker Release (CE deb) <docker@docker.com> sub rsa4096 2017-02-22 [S]
1.1.5 设置稳定版仓库 1 sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
1.2.1 更新 apt 包索引
1 sudo apt-get install docker-ce docker-ce-cli containerd.io
1.2.3 测试 docker 1 sudo docker run hello-world
输出以下内容表示成功了!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world e6590344b1a5: Pull complete Digest: sha256:e0b569a5163a5e6be84e210a2587e7d447e08f87a0e90798363fa44a0464a1e8 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
1.2.4 查看 docker 版本
1.2.5 docker 服务启动与停止 1 2 3 4 5 6 sudo service docker startsudo service docker restartsudo service docker stop
1.2.6 查看 docker 镜像 注意要先启动 docker 服务
1.2.7 开机自动启动 docker 服务 1 sudo systemctl enable docker
2.docker 常用知识 不同操作系统下其安装包、运行环境是都不相同的!如果是手动安装,必须手动解决安装包不同、环境不同的、配置不同的问题!
而使用 Docker,这些完全不用考虑。就是因为 Docker 会自动搜索并下载 MySQL。注意:这里下载的不是安装包,而是镜像。镜像中不仅包含了 MySQL 本身,还包含了其运行所需要的环境、配置、系统级函数库。因此它在运行时就有自己独立的环境,就可以跨系统运行,也不需要手动再次配置环境了。这套独立运行的隔离环境我们称为容器。
镜像:英文是 image
容器:英文是 container
2.1 安装 mysql 2.1.1 安装命令 1 2 3 4 5 6 sudo docker run -d \ --name mysql \ -p 3306:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=123 \ mysql
2.1.2 命令参数解读 这里对命令各个参数的解释如下:
sudo docker run -d
docker run
:创建并启动一个新的容器。
-d
:以后台(守护进程)模式运行容器。
--name mysql
指定容器的名字为 “mysql”,方便后续管理和使用容器。
-p 3306:3306
: 设置端口映射。
容器是隔离环境,外界不可访问。但是可以将宿主机端口映射容器内到端口,当访问宿主机指定端口时,就是在访问容器内的端口了。
容器内端口往往是由容器内的进程决定,例如 MySQL 进程默认端口是 3306,因此容器内端口一定是 3306;而宿主机端口则可以任意指定,一般与容器内保持一致。
格式: -p 宿主机端口:容器内端口,示例中就是将宿主机的 3306 映射到容器内的 3306 端口
-e TZ=Asia/Shanghai
: 配置容器内进程运行时的一些参数
格式:-e KEY=VALUE,KEY 和 VALUE 都由容器内进程决定
案例中,TZ=Asia/Shanghai 是设置时区;MYSQL_ROOT_PASSWORD=123 是设置 MySQL 默认密码
mysql
: 设置镜像名称,Docker 会根据这个名字搜索并下载镜像
格式:REPOSITORY:TAG,例如 mysql:8.0,其中 REPOSITORY 可以理解为镜像名,TAG 是版本号
在未指定 TAG 的情况下,默认是最新版本,也就是 mysql:latest
2.2 常用命令 2.2.1 命令介绍
命令
说明
docker pull
拉取镜像
docker push
推送镜像到 Docker Registry
docker images
查看本地镜像
docker rmi
删除本地镜像
docker run
创建并运行容器(不能重复创建)
docker stop
停止指定容器
docker start
启动指定容器
docker restart
重新启动容器
docker rm
删除指定容器
docker ps
查看运行中的容器(-a 查看全部)
docker logs
查看容器运行日志
docker exec
进入容器
docker save
保存镜像到本地压缩文件
docker load
加载本地压缩文件到镜像
docker inspect
查看容器详细信息
用一张图表示它们之间的关系
2.2.2 以安装 ngnix 为例
如果报错了可以在命令之前加个 sudo。Docker 守护进程默认情况下需要超级用户权限才能访问。 感觉这样有点麻烦,可以将当前用户添加到 docker 组就不用每个命令都加 sudo 了,之后记得重启一下系统
1 sudo usermod -aG docker $USER
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 docker pull nginx docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 605c77e624dd 16 months ago 141MB mysql latest 3218b38490ce 17 months ago 516MB docker run -d --name nginx -p 80:80 nginx docker ps docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" docker stop nginx docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" docker start nginx docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" docker inspect nginx docker exec -it nginx bash docker exec -it mysql mysql -uroot -p docker rm nginx docker rm -f nginx
2.3 数据卷 容器是隔离环境,容器内程序的文件、配置、运行时产生的容器都在容器内部,我们要读写容器内的文件非常不方便。大家思考几个问题:
如果要升级 MySQL 版本,需要销毁旧容器,那么数据岂不是跟着被销毁了?
MySQL、Nginx 容器运行后,如果我要修改其中的某些配置该怎么办?
我想要让 Nginx 代理我的静态资源怎么办?
因此,容器提供程序的运行环境,但是程序运行产生的数据、程序运行依赖的配置都应该与容器解耦。
2.3.1 什么是数据卷 数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。它们之间的关联叫做挂载。 简单来说操作宿主机的内容就可以更改容器内的内容,操作容器内的内容也可以更改宿主机的内容。
/var/lib/docker/volumes 这个目录就是默认的存放所有容器数据卷的目录,其下再根据数据卷名称创建新目录,格式为/数据卷名/_data。
注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。
2.3.2 数据卷的常用命令
命令
说明
docker volume create
创建数据卷
docker volume ls
查看所有数据卷
docker volume rm
删除指定数据卷
docker volume inspect
查看某个数据卷的详情
docker volume prune
清除数据卷
示例:nginx 的 html 目录挂载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx docker volume ls DRIVER VOLUME NAMElocal 2dacf60661c98b13c9d8540bf1562fb8120de940b3a45a46891ec2b029a60628local html docker volume inspect html [ { "CreatedAt" : "2025-02-24T16:21:28+08:00" , "Driver" : "local" , "Labels" : null, "Mountpoint" : "/var/lib/docker/volumes/html/_data" , "Name" : "html" , "Options" : null, "Scope" : "local" } ] ll /var/lib/docker/volumes/html/_data root@elysia:~# ll /var/lib/docker/volumes/html/_data total 16 drwxr-xr-x 2 root root 4096 2月 24 16:21 ./ drwx-----x 3 root root 4096 2月 24 16:21 ../ -rw-r--r-- 1 root root 497 2月 5 19:06 50x.html -rw-r--r-- 1 root root 615 2月 5 19:06 index.htmlcd /var/lib/docker/volumes/html/_data vi index.html docker exec -it nginx bash
2.3.3 挂载本地目录或文件 1 2 3 4 -v 本地目录:容器内目录 -v 本地文件:容器内文件
注意:本地目录或文件必须以 / 或 ./开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。 如果无权复制文件到容器内,可以使用 chown 命令修改文件的所属用户和组。 或者直接用 root 权限连接,省的麻烦。root 连接教程
1 sudo chown -R yourusername:yourusername /path/to/target/directory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 docker rm -f mysqlcd ~ 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 \ mysqlls -l mysql 总用量 12 drwxr-xr-x 2 root root 4096 2月 26 23:03 conf drwxr-xr-x 8 systemd-coredump root 4096 2月 26 23:07 data drwxr-xr-x 2 root root 4096 2月 26 23:03 initls -l data docker exec -it mysql mysql -uroot -p123 show variables like "%char%" ; +--------------------------+--------------------------------+ | 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/ | +--------------------------+--------------------------------+ show databases; +--------------------+ | Database | +--------------------+ | hmall | | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) use hmall; show tables; +-----------------+ | Tables_in_hmall | +-----------------+ | address | | cart | | item | | order | | order_detail | | order_logistics | | pay_order | | user | +-----------------+ +----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+ | 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)
2.4 镜像 2.4.1 镜像结构 镜像就是一堆文件的集合。 但需要注意的是,镜像文件不是随意堆放的,而是按照操作的步骤分层叠加而成,每一层形成的文件都会单独打包并标记一个唯一 id,称为 Layer(层)。这样,如果我们构建时用到的某些层其他人已经制作过,就可以直接拷贝使用这些层,而不用重复制作。
2.4.2 Dockerfile 由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以 Docker 就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给 Docker 去执行即可。 而这种记录镜像结构的文件就称为 Dockerfile,其对应的语法可以参考官方文档:https://docs.docker.com/engine/reference/builder/
指令
说明
示例
FROM
指定基础镜像
FROM centos:6
ENV
设置环境变量,可在后面指令使用
ENV key value
COPY
拷贝本地文件到镜像的指定目录
COPY ./xx.jar /tmp/app.jar
RUN
执行 Linux 的 shell 命令,一般是安装过程的命令
RUN yum install gcc
EXPOSE
指定容器运行时监听的端口,是给镜像使用者看的
EXPOSE 8080
ENTRYPOINT
镜像中应用的启动命令,容器运行时调用
ENTRYPOINT java -jar xx.jar
1 2 3 4 5 6 7 8 9 FROM openjdk:11.0-jre-buster ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone COPY docker-demo.jar /app.jar ENTRYPOINT ["java" , "-jar" , "/app.jar" ]
2.4.3 制作镜像 将提供的 docker-demo.jar 包以及 Dockerfile 拷贝到虚拟机的/root/demo 目录
1 2 3 4 cd /root/demo docker build -t docker-demo:1.0 .
docker build : 就是构建一个 docker 镜像
-t docker-demo:1.0 :-t 参数是指定镜像的名称(repository 和 tag)
. : 最后的点是指构建时 Dockerfile 所在路径,由于我们进入了 demo 目录,所以指定的是.代表当前目录,也可以直接指定 Dockerfile 目录:
运行这个镜像
1 2 3 4 5 6 7 8 9 10 11 12 13 docker run -d --name dd -p 8080:8080 docker-demo:1.0 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 curl localhost:8080/hello/count <h5>欢迎访问黑马商城, 这是您第1次访问<h5>
2.5 网络 我们创建了一个 Java 项目的容器,而 Java 项目往往需要访问其它各种中间件,例如 MySQL、Redis 等。现在,我们的容器之间能否互相访问呢?我们来测试一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 docker inspect mysql docker inspect --format='{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' mysql 172.17.0.2 docker exec -it dd bash 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 的网络功能来解决这个问题,官方文档
常见命令有:
命令
说明
文档地址
docker network create
创建一个网络
docker network create
docker network ls
查看所有网络
docs.docker.com
docker network rm
删除指定网络
docs.docker.com
docker network prune
清除未使用的网络
docs.docker.com
docker network connect
使指定容器连接加入某网络
docs.docker.com
docker network disconnect
使指定容器连接离开某网络
docker network disconnect
docker network inspect
查看网络详细信息
docker network inspect
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 docker network create hmall docker network ls NETWORK ID NAME DRIVER SCOPE bb101b739304 bridge bridge local 7a34682225aa hmall bridge local 9bd1d9580837 host host local 89cd2e5269ff none null local f7d1b6b61018 onlinejudgedeploy_default bridge local docker network connect hmall mysql --alias db docker network connect hmall dd docker exec -it dd bash 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 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
3.JAVA 项目部署(Docker Compose) 3.1 Docker Compose Docker Compose 可以帮助我们实现多个相互关联的 Docker 容器的快速部署。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器。
docker-compose 文件中可以定义多个相互关联的应用容器,每一个应用容器被称为一个服务(service)。由于 service 就是在定义某个应用的运行时参数,因此与 docker run 参数非常相似。
docker run
参数
docker compose
指令
说明
–name
container_name
容器名称
-p
ports
端口映射
-e
environment
环境变量
-v
volumes
数据卷配置
–network
networks
网络
举例来说,用 docker run 部署 MySQL 的命令如下:
1 2 3 4 5 6 7 8 9 10 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 \ --network hmall mysql
如果用 docker-compose.yml 文件来定义,就是这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 version: "3.8" services: mysql: image: mysql container_name: mysql ports: - "3306:3306" environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: 123 volumes: - "./mysql/conf:/etc/mysql/conf.d" - "./mysql/data:/var/lib/mysql" networks: - new networks: new: name: hmall