Docker 快速上手学习入门教程

目录

1、docker 的基础概念

2、怎样打包和运行一个应用程序?

3、如何对 docker 中的应用程序进行修改?

4、如何对创建的镜像进行共享?

5、如何使用 volumes 名称对容器中的数据进行存储?// 数据挂载

6、另一种挂载方式:目录挂载

7、实现容器之间的相互通信

8、使用 Docker Compose 简化多个容器之间的共享操作


1、docker 的基础概念

        什么是容器?

        官方解释是,docker 容器是机器上的沙盒进程,它与主机上的所有其他进程隔离。所以容器只是操作系统中被隔离开来的一个进程,所谓的容器化,其实也只是对操作系统进行欺骗的一种语法糖。

        什么是容器镜像?

        容器运行的依赖文件就是镜像,通过镜像可以创建多个容器

2、怎样打包和运行一个应用程序?

(1)获取程序源文件

        准备:需要安装 git,使用 git 拉取远程代码到本地。 下边程序是一个 docker 官方的示例:

git clone https://github.com/docker/getting-started.git

(2)创建容器镜像

        创建容器镜像,需要用到 Dockerfile 文件。Dockerfile 只是一个基于文本的文件,没有文件扩展名。Dockerfile 中包含 Docker 用来创建容器映像的指令脚本。

        创建 Dockerfile 文件:在下载的 getting-started 项目中创建空的 Dockerfile 文件(注意该文件没有任何文件格式)

        填充 Dockerfile 文件内容如下(关于 Dockerfile 文件的编写后续会有专门的介绍,这里只需要知道创建容器镜像需要使用到 Dockerfile 文件即可):

# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000

        在 Dockerfile 文件的当前目录下(app 目录下),通过 docker build 命令创建容器镜像:

docker build -t getting-started .
  •  -t 表示镜像的 tags,这里的标签名称为 getting-started
  • . 表示 docker build 命令从当前文件夹下寻找 Dockerfile 文件

(3)启动运行容器        

        创建镜像成功后,使用 docker images 命令就可以在系统中查看到创建的镜像了。查看镜像后使用 docker run 命令运行创建的镜像文件:

docker run -dp 3000:3000 getting-started

        -d 表示在后台运行容器,-p 表示创建容器和本机的端口映射,端口映射是必须的,不然无法对容器中的程序进行访问。// 有人也说容器是一个虚拟机,这样想似乎能更好的解释端口映射

        访问 http://localhost:3000/ 出现以下界面,说明容器启动成功:

3、如何对 docker 中的应用程序进行修改?

        如果我们修改了应用程序,要使修改生效,就需要重新创建镜像文件(重复文章第二节中的过程)。需要注意的是,为避免端口冲突,应该先停止正在运行的容器。以下是操作容器的一些命令:

docker ps 可以获取到容器的id
docker stop <the-container-id>  通过id停止一个容器
docker rm <the-container-id>    容器停止后,删除一个容器
docker rm -f <the-container-id> -f 即force,表示强制删除

4、如何对创建的镜像进行共享?

(1)创建一个远程仓库

        如果没有 Docker ID,可以在 Docker Hub 上注册用户,然后使用 Docker Hub 创建远程仓库。创建远程仓库的步骤在官方文档中有详细介绍(文档链接地址在文章最后),大致与 git 创建远程仓库,然后推送代码的过程相似。 

(2)把镜像推送到远程仓库

        把镜像推送到远程仓库后,其他人就可以下载到你的镜像了,常用的命令如下:

docker push YOUR-USER-NAME/getting-started:tagname // 推送镜像
docker tag getting-started YOUR-USER-NAME/getting-started  //给镜像打标签
docker push YOUR-USER-NAME/getting-started // 拉取镜像

5、如何使用 volumes 名称对容器中的数据进行存储?// 数据挂载

        每次启动容器时,之前容器更新的数据都会被清除。这是因为每个容器都有自己“独立的空间”来创建/更新/删除文件。这些更改都不会在另一个容器中看到,即使它们使用的是相同的镜像。// 容器是相互隔离的

        解决上述问题的思路:使用 volumes 对数据进行存储。

        通过 volumes 可以将容器中的具体文件系统路径挂载到主机。如果容器中的一个目录被挂载,那么在主机上也会看到该目录中的更改。如果我们在容器重新启动时挂载同一个目录,我们将看到相同的文件。// docker 提供了两种挂载方式:数据挂载和目录挂载

        (1)使用 docker volume create 命令创建 volume,todo-db 为 volume 的名称

docker volume create todo-db

        (2)使用 volume 名称进行挂载,/etc/todos 路径下的所有更改都会同步到 volume 中,使用同一个 volume 的其他容器也能够看到相同的信息

        // 默认情况下,todo 应用程序将其数据存储在 SQLite 数据库中的 /etc/todos/todo.db 文件中

docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started

        那么,当我们创建容器卷(volume)后,容器中的文件具体保存在物理机的哪个地方呢?使用 docker volume inspect 命令,查看容器卷的详细信息

$ docker volume inspect todo-db
[
    {
        "CreatedAt": "2023-02-07T01:34:40Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": {},
        "Scope": "local"
    }
]

        Mountpoint 就是文件在磁盘上的具体存储路径(自动生成的),但是,在大多数计算机上,这个路径需要具有根访问权限才能从主机访问此目录。// windows 系统也是这个路径,这个路径在 win 系统上不能直接访问,因此会比较麻烦

6、另一种挂载方式:目录挂载

        目录挂载:允许将主机文件系统中的一个目录共享到容器中。以下是目录挂载和容器卷挂载的区别:

命名卷(volume绑定挂载(目录挂载)
主机存储位置Docker 选择自定义
绑定示例

type=volume,

src=my-volume,target=/usr/local/data

type=bind,

src=/path/to/data,target=/usr/local/data

用容器内容填充新卷
支持volume驱动程序

        示例:在目录 getting-started/app 输入如下命令(win),注意,使用的是 PowerShell 而不是 cmd 命令启用的黑窗口,如果仍然报错可以使用编辑工具把以下命令编辑成一行

docker run -dp 3000:3000 `
    -w /app --mount type=bind,src="$(pwd)",target=/app `
    node:18-alpine `
    sh -c "yarn install && yarn run dev"
  • -dp 3000:3000 端口映射
  • -w /app 设置工作目录或命令运行的当前目录
  • --mount type=bind,src="$(pwd)",target=/app 把主机的当前目录绑定到容器中的 /app 目录
  • node:18-alpine 程序运行需要依赖的基础镜像(在上文 DockerFile 中也有写)
  • sh -c "yarn install && yarn run dev" 使用 sh 运行 shell,使用 yarn install 安装依赖包,使用 yarn run dev 启动一个服务(dev 脚本定义在 getting-started\app\package.json 文件中,它会启动 nodemon)

        nodemon 是一个工具,当程序有改动时,nodemon 程序用来自动重启容器。当然,我们也可以用第二节提到的步骤对程序进行打包然后重新启动。

        容器启动后,使用如下命令查看 docker 的运行日志:

docker logs -f <container-id>

7、实现容器之间的相互通信

        默认情况下,docker 之间是相互独立的,彼此之间相互隔离,那么怎么样让相互隔离的两个容器进行通信呢?// 比如部署应用程序的 docker 和部署数据库的 docker 之间进行通信

        答案是:在 docker 之间建立通信网络,在同一个通信网络的不同容器之间可以进行相互通信。一般将容器放到一个网络中有两种方法:1、在启动容器时进行分配,2、连接到已有的容器的网络。下边将分别使用到这两种方式。// 每一节的案例都需要关闭之前启动的容器,避免端口冲突

(1)创建一个通信网络

docker network create todo-app

(2)启动一个 mysql 容器,并连接到 todo-app 网络(win PowerShell 版)

docker run -d `
     --network todo-app --network-alias mysql `
     -v todo-mysql-data:/var/lib/mysql `
     -e MYSQL_ROOT_PASSWORD=secret `
     -e MYSQL_DATABASE=todos `
     mysql:8.0
  • --network-alias 指定运行容器的别名,使用别名替换掉具体的 ip,更方便在网络中查找容器
  • -v todo-mysql-data:/var/lib/mysql 该命令会自动创建容器卷 todo-mysql-data,然后存储mysql中的数据库数据(/var/lib/mysql 为数据库存储数据的路径)

        为了查看数据库容器是否已经启动,可以尝试进入容器进行查看:// 密码是 secret,脚本中有指定

docker ps // 查看正在运行中的容器
docker exec -it <mysql-container-id> mysql -u root -p

        如果输入密码可进行登录,说明数据库已经启动了,尝试以下命令,验证 mysql 正常

mysql> SHOW DATABASES;
mysql> exit;

        那么当 mysql 启动后,怎样找到这个容器呢?答案是,使用一个  nicolaka/netshoot 的网络工具。首先我们通过 docker 来安装这个工具

docker run -it --network todo-app nicolaka/netshoot

        安装完后,就可以使用这个 DNS 工具了。//下边的 mysql 就是启动容器时指定的别名

dig mysql/容器id

        然后就能看到 mysql 容器的相关网络信息 :

        我们看到 mysql 容器的 ip 为 172.19.0.2(todo-app 网络中的地址),一般来说,我们仅仅通过 mysql 别名就可以定位到这个地址了,而不需要显示去指定它。

(3)启动应用程序容器,并连接到 mysql 容器

        todo 应用程序支持设置一些环境变量来指定 MySQL 连接设置

  • MYSQL_HOST - MySQL server 主机名称
  • MYSQL_USER - 数据库连接用户
  • MYSQL_PASSWORD - 数据库连接密码
  • MYSQL_DB - 连接的 mysql 的具体数据库

        在 getting-started\app 目录下运行以下命令(win PowerShell 版)

docker run -dp 3000:3000 `
   -w /app -v "$(pwd):/app" `
   --network todo-app `
   -e MYSQL_HOST=mysql `
   -e MYSQL_USER=root `
   -e MYSQL_PASSWORD=secret `
   -e MYSQL_DB=todos `
   node:18-alpine `
   sh -c "yarn install && yarn run dev"

        运行成功后,就可以查看到 docker 的启动日志了

        此时,我们再打开程序http://localhost:3000/往项目中添加 items,然后进入到数据库容器就可以查看到刚才添加的数据了

docker exec -it <mysql-container-id> mysql -p todos  //进入数据库容器
select * from todo_items; // 查看表中数据

        至此,我们就实现了两个容器之间的相互通信。

8、使用 Docker Compose 简化多个容器之间的共享操作

        Docker Compose 用于帮助定义和共享多容器中的应用程序。通过 Compose,我们可以创建一个 YAML 文件来定义服务,并通过一个命令,就可以启动或停止所有服务。

(1)安装  Docker Compose

        如果在 win 环境安装了 Docker Desktop,那么默认情况下就已经安装了 Docker Compose,如果是 linux 环境那么需要单独进行安装,安装教程点击这里。安装完后可以查看该工具的版本:

docker compose version

(2)编写 Compose file 文件

        在 getting-started\app 目录下创建一个 docker-compose.yml 文件

        然后在 docker-compose.yml 文件中填充以下内容:// 文档的具体编写参照文末的文档,这里只介绍大致步骤

services:
  app:
    image: node:18-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

  mysql:
    image: mysql:8.0
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

 (3)批量启动容器

        在 getting-started\app 目录下执行以下命令,-d 表示后台启动

docker compose up -d

        然后你会看到如下输出信息:

         信息中显示容器卷和通信网络都被创建了,默认情况下,Docker Compose 会自动为应用程序堆栈创建一个网络(这就是为什么我们不需要在 Compose 文件中定义一个网络的原因)。

        至此,所有的容器就都成功启动了,如果你安装了 Docker Desktop,你将看到以下界面:

(4)批量关闭和移除容器

        使用以下命令可以批量关闭和移除容器

docker compose down

        需要注意的是,以上命令并不会删除创建的容器卷,删除容器卷需要使用单独的命令来操作。

参考文档:Overview | Docker Documentation

什么是Docker Docker 最初是dotCloud 公司创始人Solomon Hykes 在法国期间发起的一个公司内部项目, 它是基于dotCloud 公司多年云服务技术的一次革新,并于2013 年3 月以Apache 2.0 授权 协议开源,主要项目代码在GitHub 上进行维护。Docker 项目后来还加入了Linux 基金会, 并成立推动开放容器联盟(OCI)。 Docker 自开源后受到广泛的关注和讨论,至今其GitHub 项目已经超过4 万6 千个星标和一 万多个fork。甚至由于Docker 项目的火爆,在2013 年底,dotCloud 公司决定改名为 DockerDocker 最初是在Ubuntu 12.04 上开发实现的;Red Hat 则从RHEL 6.5 开始对 Docker 进行支持;Google 也在其PaaS 产品中广泛应用DockerDocker 使用Google 公司推出的Go 语言进行开发实现,基于Linux 内核的 cgroup,namespace,以及AUFS 类的Union FS 等技术,对进程进行封装隔离,属于操作 系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容 器。最初实现是基于LXC,从0.7 版本以后开始去除LXC,转而使用自行开发的 libcontainer,从1.11 开始,则进一步演进为使用runC 和containerd。 Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极 大的简化了容器的创建和维护。使得Docker 技术比虚拟机技术更为轻便、快捷。 下面的图片比较了Docker 和传统虚拟化方式的不同之处。传统虚拟机技术是虚拟出一套硬件 后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程 直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比 传统虚拟机更为轻便。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

swadian2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值