docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123567 \
mysql
docker run -d
:创建并运行一个容器,-d
则是让容器以后台进程运行
--name
mysql
: 给容器起个名字叫mysql
,你可以叫别的
-p 3306:3306
: 设置端口映射。
命令 | 说明 | 文档地址 |
---|---|---|
docker pull | 拉取镜像 | docker pull |
docker push | 推送镜像到DockerRegistry | docker push |
docker images | 查看本地镜像 | docker images |
docker rmi | 删除本地镜像 | docker rmi |
docker run | 创建并运行容器(不能重复创建) | docker run |
docker stop | 停止指定容器 | docker stop |
docker start | 启动指定容器 | docker start |
docker restart | 重新启动容器 | docker restart |
docker rm | 删除指定容器 | docs.docker.com |
docker ps | 查看容器 | docker ps |
docker logs | 查看容器运行日志 | docker logs |
docker exec | 进入容器 | docker exec |
docker save | 保存镜像到本地压缩文件 | docker save |
docker load | 加载本地压缩文件到镜像 | docker load |
docker inspect | 查看容器详细信息 | docker inspect |
一张图可解释清楚:
默认情况下我们要手动开启Docker和Docker中的容器:
我们可以通过命令来实现开机的时候自动开启:
# Docker 开机自动启动
systemctl enable docker
# Docker 容器开机自启
docker update --restart=always [容器名/容器id]
例子演示:
# 第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 bash # 或者,可以进入MySQL docker exec -it mysql mysql -uroot -p # 第13步,删除容器 docker rm nginx # 发现无法删除,因为容器运行中,强制删除容器 docker rm -f nginx
我们可以设计docker的快捷键,可以通过取别名来快速格式内容:
eg:
第一步:通过修改 /root/.bashrc文件
vi /root/.bashrc
# 修改/root/.bashrc文件 vi /root/.bashrc 内容如下: # .bashrc # User specific aliases and functions alias rm='rm -i' alias cp='cp -i' alias mv='mv -i' alias dps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"' alias dis='docker images' # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi
2.执行命令,使得刚刚设计的快捷键生效
source /root/.bashrc
提问:
1.容器与镜像的区别是什么?
- 镜像是一个模板,用于创建容器;而容器是镜像的一个实例,用于实际运行应用程序。
- 镜像是静态的,容器是动态的。
2.去到公司怎么启动docker容器以及如何常看已经启动的容器?
docker start
docker ps
什么是数据卷:数据卷是一个虚拟的目录,是容器内文件与宿主机目录之间映射的桥梁。
举例:在Nginx中有两个关键的目录:html与conf
如果我想要nginx代理中的静态资源,最好是放到html目录;如果我们要修改Niginx的配置,最好是找到conf中的nginx.conf文件
一张图搞懂数据卷是怎么联系宿主机与容器的:
在上图中:
我们创建了两个数据卷:conf
、html
Nginx容器内部的conf
目录和html
目录分别与两个数据卷关联。
而数据卷conf和html分别指向了宿主机的/var/lib/docker/volumes/conf/_data
目录和/var/lib/docker/volumes/html/_data
目录
这样以来,容器内的conf
和html
目录就 与宿主机的conf
和html
目录关联起来,我们称为挂载。此时,我们操作宿主机的/var/lib/docker/volumes/html/_data
就是在操作容器内的/usr/share/nginx/html/_data
目录。只要我们将静态资源放入宿主机对应目录,就可以被Nginx代理了。
/var/lib/docker/volumes
这个目录就是默认的存放所有容器数据卷的目录,其下再根据数据卷名称创建新目录,格式为/数据卷名/_data
。为什么不让容器目录直接指向宿主机目录呢?
因为直接指向宿主机目录就与宿主机强耦合了,如果切换了环境,宿主机目录就可能发生改变了。由于容器一旦创建,目录挂载就无法修改,这样容器就无法正常工作了。
但是容器指向数据卷,一个逻辑名称,而数据卷再指向宿主机目录,就不存在强耦合。如果宿主机目录发生改变,只要改变数据卷与宿主机目录之间的映射关系即可。
不过,我们通过由于数据卷目录比较深,不好寻找,通常我们也允许让容器直接与宿主机目录挂载而不使用数据卷
命令 | 说明 | 文档地址 |
---|---|---|
docker volume create | 创建数据卷 | docker volume create |
docker volume ls | 查看所有数据卷 | docs.docker.com |
docker volume rm | 删除指定数据卷 | docs.docker.com |
docker volume inspect | 查看某个数据卷的详情 | docs.docker.com |
docker volume prune | 清除数据卷 | docker volume prune |
镜像就是包括了应用程序、程序运行的系统函数库、运行配置等文件的文件包。构建镜像的过程就是其实把上述文件打包的过程。
部署一个Java应用的步骤:
(1)准备一个Linux服务器
(2)安装JRE并配置环境变量
(3)拷贝Jar包
(4)运行Jar包
ps:JRE是运行时环境,它提供了 Java 虚拟机(JVM)、核心类库以及其他支持文件,允许用户在其计算机上执行 Java 程序。
不同的操作系统用的JVM是不一样的。
构建一个Java镜像的步骤:
(1)准备一个Linyx运行环境
(2)安装JRE并且配置环境变量
(3)拷贝Jar包
(4)编写运行脚本
docker镜像由很多压缩包组成,就是每一层(Layer)添加安装包、依赖、配置等。
在制作镜像的时候, 可以共享基础的层。(BaseImage) 应用依赖的系统函数库、环境、配置、文件。
而这种记录镜像结构的文件就称为Dockerfile,其对应的语法可以参考官方文档:
https://docs.docker.com/engine/reference/builder/
其中的语法比较多,比较常用的有:
指令 | 说明 | 示例 |
---|---|---|
FROM | 指定基础镜像 |
|
ENV | 设置环境变量,可在后面指令使用 |
|
COPY | 拷贝本地文件到镜像的指定目录 |
|
RUN | 执行Linux的shell命令,一般是安装过程的命令 |
|
EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT java -jar xx.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"]
3.3 构建镜像
docker build -t myI mage:1.0 .
怎么加载jar包呢? docker load -i jdk.tar
# 进入镜像目录 cd /root/demo # 开始构建 docker build -t docker-demo:1.0 .
命令说明:
docker build
: 就是构建一个docker镜像
-t docker-demo:1.0
:-t
参数是指定镜像的名称(repository
和tag
)
.
: 最后的点是指构建时Dockerfile所在路径,由于我们进入了demo目录,所以指定的是.
代表当前目录,也可以直接指定Dockerfile目录
查看镜像:
# 查看镜像列表: docker images # 结果 REPOSITORY TAG IMAGE ID CREATED SIZE docker-demo 1.0 d6ab0b9e64b9 27 minutes ago 327MB nginx latest 605c77e624dd 16 months ago 141MB mysql latest 3218b38490ce 17 months ago 516MB
运行镜像:
# 1.创建并运行容器 docker run -d --name dd -p 8080:8080 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 # 结果: 欢迎访问黑马商城, 这是您第1次访问
容器的网络IP其实是一个虚拟的IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个IP,而在部署时很可能MySQL容器的IP会发生变化,连接会失败。
所以,我们必须借助于docker的网络功能来解决这个问题,官方文档:
https://docs.docker.com/engine/reference/commandline/network/
常见命令有:
命令 | 说明 | 文档地址 |
---|---|---|
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.首先通过命令创建一个网络 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
我们现在要做的就是把整个nginx目录上传到虚拟机的/root
目录下:
然后创建nginx容器并完成两个挂载:
把/root/nginx/nginx.conf
挂载到/etc/nginx/nginx.conf
把/root/nginx/html
挂载到/usr/share/nginx/html
由于需要让nginx同时代理hmall-portal和hmall-admin两套前端资源,因此我们需要暴露两个端口:
18080:对应hmall-portal
18081:对应hmall-admin
命令如下:
docker run -d \ --name nginx \ -p 18080:18080 \ -p 18081:18081 \ -v /root/nginx/html:/usr/share/nginx/html \ -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf \ --network hmall \ nginx
# 1.构建项目镜像,不指定tag,则默认为latest docker build -t hmall . # 2.查看镜像 docker images # 结果 REPOSITORY TAG IMAGE ID CREATED SIZE hmall latest 0bb07b2c34b9 43 seconds ago 362MB docker-demo 1.0 49743484da68 24 hours ago 327MB nginx latest 605c77e624dd 16 months ago 141MB mysql latest 3218b38490ce 17 months ago 516MB # 3.创建并运行容器,并通过--network将其加入hmall网络,这样才能通过容器名访问mysql docker run -d --name hmall --network hmall -p 8080:8080 hmall
测试,通过浏览器访问:http://你的虚拟机地址:8080/search/list
docker-compose.yml文件的基本语法可以参考官方文档:
https://docs.docker.com/compose/compose-file/compose-file-v3/
docker-compose文件中可以定义多个相互关联的应用容器,每一个应用容器被称为一个服务(service)。由于service就是在定义某个应用的运行时参数,因此与docker run
参数非常相似。
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
docker run 参数 | docker compose 指令 | 说明 |
---|---|---|
--name | container_name | 容器名称 |
-p | ports | 端口映射 |
-e | environment | 环境变量 |
-v | volumes | 数据卷配置 |
--network | networks | 网络 |
明白了其中的对应关系,相信编写docker-compose
文件应该难不倒大家。
黑马商城部署文件:
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" - "./mysql/init:/docker-entrypoint-initdb.d" networks: - hm-net hmall: build: context: . dockerfile: Dockerfile container_name: hmall ports: - "8080:8080" networks: - hm-net depends_on: - mysql nginx: image: nginx container_name: nginx ports: - "18080:18080" - "18081:18081" volumes: - "./nginx/nginx.conf:/etc/nginx/nginx.conf" - "./nginx/html:/usr/share/nginx/html" depends_on: - hmall networks: - hm-net networks: hm-net: name: hmall
基本语法如下:
docker compose [OPTIONS] [COMMAND]
其中,OPTIONS和COMMAND都是可选参数,比较常见的有:
类型 | 参数或指令 | 说明 |
---|---|---|
Options | -f | 指定compose文件的路径和名称 |
-p | 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念 | |
Commands | up | 创建并启动所有service容器 |
down | 停止并移除所有容器、网络 | |
ps | 列出所有启动的容器 | |
logs | 查看指定容器的日志 | |
stop | 停止容器 | |
start | 启动容器 | |
restart | 重启容器 | |
top | 查看运行的进程 | |
exec | 在指定的运行中容器中执行命令 |
# 1.进入root目录 cd /root # 2.删除旧容器 docker rm -f $(docker ps -qa) # 3.删除hmall镜像 docker rmi hmall # 4.清空MySQL数据 rm -rf mysql/data # 5.启动所有, -d 参数是后台启动 docker compose up -d # 结果: [+] Building 15.5s (8/8) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 358B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/openjdk:11.0-jre-buster 15.4s => [1/3] FROM docker.io/library/openjdk:11.0-jre-buster@sha256:3546a17e6fb4ff4fa681c3 0.0s => [internal] load build context 0.0s => => transferring context: 98B 0.0s => CACHED [2/3] RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 0.0s => CACHED [3/3] COPY hm-service.jar /app.jar 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:32eebee16acde22550232f2eb80c69d2ce813ed099640e4cfed2193f71 0.0s => => naming to docker.io/library/root-hmall 0.0s [+] Running 4/4 ✔ Network hmall Created 0.2s ✔ Container mysql Started 0.5s ✔ Container hmall Started 0.9s ✔ Container nginx Started 1.5s # 6.查看镜像 docker compose images # 结果 CONTAINER REPOSITORY TAG IMAGE ID SIZE hmall root-hmall latest 32eebee16acd 362MB mysql mysql latest 3218b38490ce 516MB nginx nginx latest 605c77e624dd 141MB # 7.查看容器 docker compose ps # 结果 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS hmall root-hmall "java -jar /app.jar" hmall 54 seconds ago Up 52 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp mysql mysql "docker-entrypoint.s…" mysql 54 seconds ago Up 53 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp nginx nginx "/docker-entrypoint.…" nginx 54 seconds ago Up 52 seconds 80/tcp, 0.0.0.0:18080-18081->18080-18081/tcp, :::18080-18081->18080-18081/tcp