文章目录
背景
软件开发最大的麻烦事之一,就是环境配置。用户计算机的环境都不相同,你怎么知道自家的软件,能在那些机器跑起来?
用户必须保证两件事: 操作系统的设置 和 各种库和组件的安装。只有他们都正确, 软件才能运行起来。
例如, 一些老旧模块在新的配置环境中, 无法使用。
环境配置如此麻烦, 换一台机器, 就要重新一次, 非常费时。有一个从根本问题解决的办法, 就是把原始环境一模一样地赋值过来。
虚拟机
虚拟机就是带环境安装的一种解决方案。它可以在一种操作系统里面运行两一种操作系统, 比如在Windows系统里面运行Linux系统。
缺点:
- 占用资源多。虚拟机会独占一部分内存和磁盘空间。
- 冗余步骤多。虚拟机时完整的操作系统, 一些系统级别的操作步骤,往往无法跳过。
- 启动慢。
Linux容器
Linux容器不是模拟一个完整的操作系统, 而是对进程进行隔离。
换一个说法, 相当于在进程外加一个保护层, 与系统底层进行隔离, 而容器里面的资源是虚拟的,而且与系统隔离的。
相比虚拟机, 它的优点:
- 启动快。容器里面的应用,直接就是底层系统的一个进程,而不是虚拟机内部的进程。启动一个进程要比系统要快得多。
- 资源占用少。容器只占用需要的资源,不占用那些没有用到的资源。虚拟机还会占用额外无用的资源。另外,多个容器可以共享资源,虚拟机都是独享资源。
- 体积小。容器只要包含用到的组件即可,而虚拟机是整个操作系统的打包,所以容器文件比虚拟机文件要小很多。
Docker的概念和用途
概念
Docker属于Linux容器的一种封装, 提供简单易用的容器使用接口。
Docker将应用程序与程序的依赖, 打包在一个文件里面。运行这个文件, 就会生成一个虚拟容器。
Docker的接口相当简单, 用户可以方便地创建和使用容器, 把直接的应用放入容器中。容器还可以进行版本管理, 复制, 分享, 修改, 就像管理普通代码一样。
用途
- 提供一次性的环境。比如, 本地测试他人的软件, 持续集成的时候提供单元测试和构建的环境。
- 提供弹性的云服务。因为Docker容器可以隋开随关, 很适合动态扩容和缩容。
- 组建微服务架构。通过多个容器, 一台机器可以跑多个服务, 因此在本机就可以模拟处微服务架构。
Docker安装
安装步骤
参考 https://www.runoob.com/docker/ubuntu-docker-install.html
基本用法
启动
安装完成后, 运行下面的命令, 验证是否安装成功。
docker version
#或
docker info
Docker需要用户具有sudo权限, 为了避免每次命令都输入sudo, 可以把用户假如Docker用户组。
sudo usermod -aG docker $USER
Docker是服务器—客户端架构。命令运行docker命令时, 需要本机有Docker服务。
#service 命令的用法
sudo service docker start
#systemctl 命令的用法
sudo systemctl start docker
ps -ef | grep docker
#输出
00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
image文件
Docker把应用程序及其依赖, 打包在一个image文件里面。 image文件可以看作是容器的模板, Docker根据image文件生成容器的实例, 同一个image文件, 可以生成多个同时运行的容器实例。
在实际开发中,我们可以对image文件做一些,定制化的处理, 比如加入其他应用程序。
# 列出本机的所有image文件
docker image ls
# 删除image文件
docker image rm [imageName]
# 或者 通过imageid删除image文件
docker image rmi [imageid]
Docker官方仓库Docker Hub是最重要, 最常用的image仓库,可以在这里分享自己image文件。
示例 - 启动容器 & 容器操作
将image文件从仓库抓取到本地
docker image pull library/hello-world
docker image pull: 抓取image文件的命令。
library/hello-world: image文件在仓库里面的位置。library是image文件所在的组, hello-world是image文件的名字。
将默认远程仓库(国外)修改国内参考: https://www.ruanyifeng.com/blog/2018/02/docker-wordpress-tutorial.html
从image文件中, 生成一个正在运行的容器实例。
docker container run hello-world
#如果本地没有指定的image文件, 就会从仓库中抓取
#所以docker image pull不是必要的
#输出信息
Hello from Docker!
This message shows that your installation appears to be working correctly.#表示hello world 停止运行, 容器自动终止
有些容器不会自动终止,因为提供的是服务。比如,安装运行 Ubuntu 的 image,就可以在命令行体验 Ubuntu 系统。
docker container run -it ubuntu /bin/bash
#-i: 交互式操作。
#-t: 终端。
#/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
#在后台运行, 加-d指定容器的运行模式
docker container run -itd ubuntu /bin/bash
#指定容器的名字
docker container run -itd --name ubuntu-test ubuntu /bin/bash
注: 如果-d指定容器在后台运行, 想要进入容器,可以使用以下命令
docker container exec -it [containID] /bin/bash
#或者
docker exec -it [containID] /bin/bash
终止容器
docker container kill [containID]
容器文件
当image文件实例化成容器时, 会生成容器文件。
#列出本机正在运行的容器
docker container ls
#列出本机所有容器, 包括终止运行的容器, 只能列出一行
docker container ls -all
#或者
#列出本机所有容器, 包括终止运行的容器
docker ps -a
#输出
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
304b1690e9c2 hello-world "/hello" 2 hours ago Exited (0) 2 hours ago naughty_austin
#当使用命令docker container kill [containID], 容器文件并不会删除
#可以使用docker container rm命令删除容器文件
docker container rm [containID]
#注: 正在运行的容器无法删除, 需要先kill掉容器再rm
#删除所有处于终止状态的容器
docker container prune
制作docker文件
image文件又是如何制作的?如果要推广自己的软件, 势必要自己制作image文件。
答: 这里需要用到Dockerfile文件, 它是一个文本文件, 用来配置image。Docker根据该文件生成二进制的image文件。
下载源代码
git clone https://github.com/ruanyf/koa-demos.git
cd koa-demos
编辑Dockerfile文件
FROM node:8.4
COPY . /app
WORKDIR /app
RUN npm install -registry=https://registry.npm.taobao.org
EXPOSE 3000
- FROM node:8.4: 该image文件继承官方的node image, 冒号表示标签, 这里标签式8.4, 即8.4版本的node
- COPY . /app: 将当前目录下的所有文件(处理.dockerignore排除的路径), 都拷贝进入image文件的/app目录
- WORKDIR /app: 指定接下来的工作路径为/app。
- RUN npm install:在/app目录下, 运行npm install目录安装依赖,。注意, 安装后所有的依赖, 都将打包进入image文件。
- EXPOSE 300:将容器3000端口暴露出来, 允许外部连接这个端口。
创建image文件
有了Dockerfile文件以后, 就可以使用 docker image build命令创建image文件。
docker image build -t koa-demo .
#或者
docker image build -t koa-demo:0.0.1 .
#. 表示Dockerfile文件的位置
-t
参数用来指定 image 文件的名字,后面还可以用冒号指定标签。如果不指定,默认的标签就是latest
。
查看新生成image文件koa-demo
docker image ls
生成容器
docker container run命令会从image文件生成容器。
docker container run -p 8000:3000 -it koa-demo /bin/bash
#或者
docker container run -p 8000:3000 -it koa-demo:0.0.1 /bin/bash
#也可以 将容器内部使用的网络端口随机映射到我们使用的主机上
docker container run -P -it koa-demos:0.0.1 /bin/bash
- -p参数: 容器的3000端口映射到本机的8000端口。
- -it参数: 容器的Shell映射到当前的Shell, 然后你在本机窗口输入的命令,就会传入容器。
- koa-demo:0.0.1: image文件的名字(如果有标签, 还需要提供标签, 默认是latest标签)。
- /bin/bash: 容器启动以后, 内部第一个执行的命令。这里是启动Bash, 保证用户可以使用Shell。
- -P参数: 将容器内部使用的网络端口随机映射到我们使用的主机上
容器启动之后, 运行Koa框架。
#输出
#打开本机的浏览器,访问 http://127.0.0.1:8000,网页显示"Not Found",这是因为这个 demo 没有写路由。
在启动时候, 指示容器终止运行后自动删除容器文件
docker container run --rm -p 8000:3000 -it koa-demo /bin/bash
发布image文件
容器运行成功后, 就确认了image文件的有效性。把image文件分享到网上, 让其他人使用。
注册账号&登录
#去hub.docker.com 或 cloud.docker.com注册一个账号, 并登录
docker login
本地image标注用户名和版本
docker image tag [imageName] [username]/[repository]:[tag]
#示例
docker image tag koa-demos:0.0.1 ruanyf/koa-demos:0.0.1
#也可以不标注用户名, 重新构建一下image文件
docker image build -t [username]/[repository]:[tag] .
发布image文件
docker image push [username]/[repository]:[tag]
补充
上述例子中,容器启动之后, 需要手动输入命令 node demos/01.js。可以把这个命令写在Dockerfile里面, 容器启动之后, 就不需要手动输入
FROM node:8.4
COPY . /app
WORKDIR /app
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000
CMD node demos/01.js
RUN命令在image文件的构建阶段执行, 执行结果都会打包进入image文件, CMD命令是在容器启动后执行。
注:
- 一个Dockerfile可以包含多个RUN命令, 但只能有一个CMD命令。
- CMD命令之后, docker container run命令就不能附加命令了(比如前面的/bin/bash),否则会覆盖CMD命令。
补充
容器操作
#docker container run是新建容器, 每运行一次, 就会新建一个容器。运行两次就会有两个容器。
docker container start [containerID]#用来启动已经生成, 已经停止运行的容器文件。相当于重启
#docker container kill是终止容器运行, 相当于向容器里面的主进程发出SIGKILL信号。
docker container stop [containerID]#向容器里面的主进程发出SIGTERM信号, 然后过一段时间发出SIGKILL信号
#查看 docker 容器的输出,即容器里面 Shell 的标准输出。如果生成容器没有指定-it参数,可以使用该命令
#输出shell已经输出的内容
docker container logs [containerID]
docker container logs -f [containerID]
#-f: 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。
#用于进入一个正在运行的 docker 容器, 就可以在容器shell执行命令
#进入容器shell, 可多个用户执行
docker container exec -it [containerID] /bin/bash
#用于从正在运行的Docker容器里面, 将文件拷贝到本机
docker container cp [containerID]:[path/to/file] .
#查看容器内部运行的进程
docker top [containerID]
#或
docker top [containername]
导出和导入容器
导出容器快照
如果要导出本地某个容器, 可以使用docker export命令
docker export [containerid] > xxx.tar
#例
docker export 1e560fca3906 > mag-media.tar
导入容器快照
使用docker import从容器快照文件中再导入为镜像。
docker import [container.tar] [imagename]
#例
docker import mag-media.tar mag-media1
分清楚概念:
- docker是工具
- image是一个文件
- 容器实际上是系统的一个进程
- image仓库: Docker Hub
- Dockerfile是生成image文件的脚本文件
docker-compose
基础
Compose是用于定义和运行多容器Docker应用程序的工具。通过Compose, 可以使用YML文件来配置应用程序需要的所有服务。使用一个命令, 就可以从YML文件配置中创建并启动所有服务。
Compose使用的三个步骤:
- 使用Dokcerfile定义应用程序的环境。
- 使用docker-compse.yml定义构成应用程序的服务, 这样它们可以在隔离环境中一起运行。
- 最后, 执行docker-compose up命令来启动并运行整个应用程序。
docker-compose.yml配置实例:
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
构建&运行docker应用
docker-compose up
#在后台运行服务
docker-compose up -d
Compose安装
参考: https://www.runoob.com/docker/docker-compose.html
问题:
-
denied: requested access to the resource is denied: https://blog.csdn.net/zzq060143/article/details/106630934
-
docker镜像源更换
vi /etc/docker/daemon.json { "registry-mirrors" : ["http://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn"] } systemctl restart docker.service
Docker中国区官方镜像 https://registry.docker-cn.com 网易 http://hub-mirror.c.163.com ustc https://docker.mirrors.ustc.edu.cn 中国科技大学 https://docker.mirrors.ustc.edu.cn
-
error response from daemon: conflict: unable to delete bfa4ecb5eec1 (must be forced) - image is being used by stopped container 86626e747b
#先删除容器 docker container rm [containerid] #再删除镜像 docker rmi [imageid]