docker 使用入门

docker 使用入门

在公司使用微服务以后,由于各个服务之间有依赖关系,调试本身服务的时候每次都须要编译运行其余服务,原来使用一台开发机做为开发环境的方式就很麻烦,因此考虑用 docker 部署一套能够复用的开发环境。首先了解下docker的基本使用。html

安装

点击连接下载 docker-desktop ,而后傻瓜式安装。node

安装好以后能够在命令行执行 docker --version 命令,查看 docker 是否正常运行。python

教程

官方确定有教程的,因此能够去官网找一下,我这边看的是 docker/getting-started 的教程。docker/getting-started 自己就是一个 dockerrepo。下面说一下怎么看这个教程。mysql

在安装好 docker 以后,在命令行运行 docker run -d -p 80:80 docker/getting-started 命令, 而后就启动了一个容器。sql

而后本地浏览器访问 http://localhost/tutorial/ 能够看到教程。英文的,可是很好理解,有点英语基础均可以看懂。本篇教程也是按照这个教程来的,记录下方便之后本身用。docker

接下来只讲使用,不讲原理。shell

使用

建立第一个本身的APP

教程提供了一个 Node.js 的应用让咱们直接使用,点击下载 Node.js APP , 本地的链接,上述步骤没作下载不下来。数据库

将下载的 zip 文件解压,用编辑器打开, 这边我用的是 vscode浏览器

建立该APP镜像

  1. 在下载的 APP 的跟目录下建立一个名称为 Dockerfile 的文件,文件内容以下:
FROM node:12-alpine
RUN apk add --no-cache python g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
  1. APP 跟目录下运行以下命令:
docker build -t getting-started .

-t 是给镜像取个名字,名字是 getting-started 。 最后的 . 表明的是运行的是当前目录下的 Dockerfile 文件。网络

启动一个APP容器

  1. 使用 docker run 命令启动一个容器,启动的时候要指定使用刚才构建的镜像。命令以下:
docker run -dp 3000:3000 getting-started
  1. 启动以后,在本地浏览器输入 http://localhost:3000 。能够看到一个 todo list 应用。
  2. 你能够在应用中使用一下。若是是本身的应用基本就可使用了。

你如今能够看下下载的 docker-desktop 面板,里面有两个容器,一个是用来看教程的,一个是新建立的本身的 APP

更新APP容器

启动容器后,容器内的应用代码确定不是一成不变的,加个需求不是很正常的事情嘛,因此须要在更改代码以后,从新构建镜像,用新镜像从新启动容器。

  1. 修改代码,在 src/static/js/app.js 文件下更新第 56 行
-                <p className="text-center">No items yet! Add one above!</p>
+                <p className="text-center">You have no todo items yet! Add one above!</p>
  1. 从新构建镜像
docker build -t getting-started .
  1. 删除原有容器,不删除原有容器直接启动会由于 3000 端口占用启不起来。能够用命令删除,或者直接在 docker-desktop 面板上直接删除。下面介绍下命令删除。
  • 首先用命令 docker ps 找到全部启动的容器。以下图:
    image.png
  • 图中第一列就是容器id,而后还用 docker rm <the-container-id> 命令删除该容器。
  1. 根据新镜像从新启动容器,命令以下。
docker run -dp 3000:3000 getting-started
  1. 从新看下应用 http://localhost:3000

持久化数据库

docker 中每一个容器的文件系统都是独立的,一个容器没法访问到另外一个容器的文件。同一个容器,再重启后旧容器中的文件就丢了。因此上面的 todo list APP 再容器更新后以前加的 todo 就没了。那怎么让容器更新后还能访问到以前的数据呢?

这里引出容器的 volumes 概念。 volumes 会将容器内的目录映射到宿主机的目录上,而后每次启动的时候都加载宿主机的目录,文件就不会丢了。

有两种类型的 volumes,一种是 named volumes , 另外一种是 bind mounts

named volumes

首先讲一下 named volumes :

  1. 使用 docker volume create 命令建立一个 volume 。
docker volume create todo-db
  1. 删除已经存在的 todo list APP 容器。步骤上面已经说了。
  2. docker run 命令从新启动容器,此次启动要加 -v 参数,命令以下:
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started

-v 就是指定 volumes 的意思。

  1. 刷新应用 http://localhost:3000 , 加几条新的 todo
  2. 而后删除 APP 容器,从新启动一个。
  3. 再次刷新应用,确认刚才的几条 todo 没有丢。

注:查看 Valumes 信息命令:

docker volume inspect <valumes name>

bind mounts

而后再来讲一下 bind mounts ,它会将宿主机内的目录与容器内的目录绑定,而后改变宿主机目录下的内容,容器内的也会改变,这就能够实如今宿主机改代码,及时同步到容器内。使用流程:

  1. 关闭全部的 getting-started 容器。
  2. 运行如下命令:
docker run -dp 3000:3000 \
    -w /app -v "$(pwd):/app" \
    node:12-alpine \
    sh -c "yarn install && yarn run dev"

若是是 PowerShell ,运行以下命令:

docker run -dp 3000:3000 `
    -w /app -v "$(pwd):/app" `
    node:12-alpine `
    sh -c "yarn install && yarn run dev"

命令解释以下:

  • -dp :是参数 -d ,-p 的缩写,-d表明后台运行, -p 指定端口。
  • -w /app :容器内工做目录,程序运行的目录。
  • -v "$(pwd):/app" : 这里指定了 volumes , 将宿主机的当前目录与容器的 /app 目录绑定。
  • node:12-alpine :使用的镜像
  • sh -c "yarn install && yarn run dev" :运行 shell
  1. 用命令 docker logs -f <container-id> 查看日志,若是你看到如下内容表明启动成功:
docker logs -f <container-id>
$ nodemon src/index.js
[nodemon] 1.19.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Using sqlite database at /etc/todos/todo.db
Listening on port 3000
  1. 尝试着改代码,将 src/static/js/app.js 文件的 109 行 "Add Item" 改为 "Add":
-                         {submitting ? 'Adding...' : 'Add Item'}
+                         {submitting ? 'Adding...' : 'Add'}
  1. 刷新网页看效果。

建立一个多容器的 APP

todo list APP 以前用的是 SQLite Database 来做为存储的。如今使用个更通用的,好比 MYSQL。 固然能够直接把 MYSQLAPP 部署到同一台机器上,可是 docker 不建议这么作。 docker 但愿每一个容器内的功能单一。因此如今的部署方案是两个容器,一个部署 MYSQL ,一个部署 APP 。 像这样:
image.png

这样两个容器之间须要经过网络链接。这样就引出 network 概念。同一个 network 上的容器能够相互通讯。

建立启动MYSQL容器

  1. 建立一个 network :
docker network create todo-app
  1. 启动一个 MYSQL 容器,将该容器链接到上一步建立的 network 上面。
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:5.7

若是用的 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:5.7

这里用到了 --network-alias, 该属性的意思是: 其余容器链接 mysql 填写 host 的时候,直接填 --network-alias 的值 mysql 就行。至关于域名。

  1. 确认mysql容器是否正常运行
docker exec -it <mysql-container-id> mysql -p

链接到mysql以后运行:

mysql> SHOW DATABASES;

能够看到 todos 库:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| todos              |
+--------------------+
5 rows in set (0.00 sec)

启动 APP 容器链接到 MYSQL

  1. 关闭全部的 getting-started 容器。
  2. 从新启动容器
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:12-alpine \
  sh -c "yarn install && yarn run dev"

若是是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:12-alpine `
  sh -c "yarn install && yarn run dev"

新增了 --network todo-app 来链接到 todo-app 网络,确保跟 mysql 一个网络就好。

同时新增了几个 -e 参数,表明指定要链接的mysql的环境变量。

  1. 查看日志 docker logs <container-id> , 会看到以下内容:
# Previous log messages omitted
$ nodemon src/index.js
[nodemon] 1.19.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Connected to mysql db at host mysql
Listening on port 3000
  1. 打开网页 http://localhost:3000 新加几个 todo
  2. 运行命令链接到 mysql :
docker exec -it <mysql-container-id> mysql -p todos

运行以下命令查看是否有新增的数据:

mysql> select * from todo_items;

Docker compose

启动了 todo listmysql 以后,在 docker-desktop 面板上看到的是两个容器,可是两个容器是有联系的,会同时启动和关闭,那该怎么让两个容器联动起来呢?

这里就要用到 docker compose ,经过一个 YAML 文件,能够同时启动和关闭两个容器,或者叫一组相关容器。

  1. 在项目的根目录下建立一个 docker-compose.yml 文件,跟最开始的 Dockerfile 同一目录下。
  2. 文件内容以下:
version: "3.7"

services:
  app:
    image: node:12-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:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:
  1. 删除刚才建立的 getting-startedmysql 两个容器。
  2. 在项目根目录下运行以下命令启动这组容器:
docker-compose up -d

运行的时候回看到以下输出:

Creating network "app_default" with the default driver
Creating volume "app_todo-mysql-data" with default driver
Creating app_app_1   ... done
Creating app_mysql_1 ... done

注意到 volumenetwork 都建立了,即便 network 没有指定。这是由于默认状况下,compose 会建立一个公共的 network

  1. 接着能够用 docker-compose logs -f 命令看下日志。
  2. 刷新下浏览器,如今能够正常使用了。而后能够观察下 docker-desktop 面板,能够看到两个容器放在了一块儿。
  3. 而后能够经过 docker-compose down 命令或者直接在面板上点击关闭这组容器。

总结

由于要搭建环境,将 docker 官网的内容整理简化,记录出image.png

相关文章
相关标签/搜索