docker 应用入门
在公司应用微服务之后,因为各个服务之间有依赖关系,调试本人服务的时候每次都须要编译运行其余服务,原来应用一台开发机作为开发环境的形式就很麻烦,所以思考用 docker
部署一套能够复用的开发环境。首先理解下 docker
的根本应用。
装置
点击链接下载 docker-desktop,而后傻瓜式装置。
装置好之后能够在命令行执行 docker --version
命令,查看 docker
是否失常运行。
教程
官网必定有教程的,所以能够去官网找一下,我这边看的是 docker/getting-started
的教程。docker/getting-started
自身就是一个 docker
的 repo
。上面说一下怎么看这个教程。
在装置好 docker
之后,在命令行运行 docker run -d -p 80:80 docker/getting-started
命令,而后就启动了一个容器。
而后本地浏览器拜访 http://localhost/tutorial/
能够看到教程。英文的,然而很好了解,有点英语根底都能够看懂。本篇教程也是依照这个教程来的,记录下不便当前本人用。
接下来只讲应用,不讲原理。
应用
创立第一个本人的 APP
教程提供了一个 Node.js
的利用让咱们间接应用,点击下载 Node.js APP,本地的连贯,上述步骤没做下载不下来。
将下载的 zip 文件解压,用编辑器关上,这边我用的是 vscode
。
创立该 APP 镜像
- 在下载的
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"]
- 在
APP
跟目录下运行如下命令:
docker build -t getting-started .
-t
是给镜像取个名字,名字是 getting-started
。最初的 .
代表的是运行的是当前目录下的 Dockerfile
文件。
启动一个 APP 容器
- 应用
docker run
命令启动一个容器,启动的时候要指定应用方才构建的镜像。命令如下:
docker run -dp 3000:3000 getting-started
- 启动之后,在本地浏览器输出 http://localhost:3000。能够看到一个
todo list
利用。 - 你能够在利用中应用一下。如果是本人的利用根本就能够应用了。
你当初能够看下下载的 docker-desktop
面板,外面有两个容器,一个是用来看教程的,一个是新创建的本人的 APP
。
更新 APP 容器
启动容器后,容器内的利用代码必定不是变化无穷的,加个需要不是很失常的事件嘛,所以须要在更改代码之后,从新构建镜像,用新镜像重新启动容器。
- 批改代码,在
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>
- 从新构建镜像
docker build -t getting-started .
- 删除原有容器,不删除原有容器间接启动会因为
3000
端口占用启不起来。能够用命令删除,或者间接在docker-desktop
面板上间接删除。上面介绍下命令删除。
- 首先用命令
docker ps
找到所有启动的容器。如下图: - 图中第一列就是容器 id,而后还用
docker rm <the-container-id>
命令删除该容器。
- 依据新镜像重新启动容器,命令如下。
docker run -dp 3000:3000 getting-started
- 从新看下利用 http://localhost:3000。
长久化数据库
docker
中每个容器的文件系统都是独立的,一个容器无法访问到另一个容器的文件。同一个容器,再重启后旧容器中的文件就丢了。所以下面的 todo list APP
再容器更新后之前加的 todo
就没了。那怎么让容器更新后还能拜访到之前的数据呢?
这里引出容器的 volumes
概念。volumes
会将容器内的目录映射到宿主机的目录上,而后每次启动的时候都加载宿主机的目录,文件就不会丢了。
有两种类型的 volumes
,一种是 named volumes,另一种是 bind mounts。
named volumes
首先讲一下 named volumes :
- 应用
docker volume create
命令创立一个 volume。
docker volume create todo-db
- 删除曾经存在的
todo list APP
容器。步骤下面曾经说了。 - 用
docker run
命令重新启动容器,这次启动要加-v
参数,命令如下:
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
-v
就是指定 volumes
的意思。
- 刷新利用 http://localhost:3000,加几条新的
todo
。 - 而后删除
APP
容器,重新启动一个。 - 再次刷新利用,确认方才的几条
todo
没有丢。
注:查看
Valumes
信息命令:docker volume inspect <valumes name>
bind mounts
而后再来说一下 bind mounts,它会将宿主机内的目录与容器内的目录绑定,而后扭转宿主机目录下的内容,容器内的也会扭转,这就能够实现在宿主机改代码,及时同步到容器内。应用流程:
- 敞开所有的
getting-started
容器。 - 运行以下命令:
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
- 用命令
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
- 尝试着改代码,将
src/static/js/app.js
文件的 109 行 “Add Item” 改成 “Add”:
- {submitting ? 'Adding...' : 'Add Item'}
+ {submitting ? 'Adding...' : 'Add'}
- 刷新网页看成果。
创立一个多容器的 APP
该 todo list APP
之前用的是 SQLite Database 来作为存储的。当初应用个更通用的,比方 MYSQL
。当然能够间接把 MYSQL
跟 APP
部署到同一台机器上,然而 docker
不倡议这么做。docker
心愿每个容器内的性能繁多。所以当初的部署计划是两个容器,一个部署 MYSQL
,一个部署 APP
。像这样:
这样两个容器之间须要通过网络连接。这样就引出 network 概念。同一个 network 上的容器能够互相通信。
创立启动 MYSQL 容器
- 创立一个 network :
docker network create todo-app
- 启动一个 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
就行。相当于域名。
- 确认
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
- 敞开所有的
getting-started
容器。 - 重新启动容器
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
的环境变量。
- 查看日志
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
- 关上网页 http://localhost:3000 新加几个
todo
。 - 运行命令连贯到
mysql
:
docker exec -it <mysql-container-id> mysql -p todos
运行如下命令查看是否有新增的数据:
mysql> select * from todo_items;
Docker compose
启动了 todo list
和 mysql
之后,在 docker-desktop
面板上看到的是两个容器,然而两个容器是有分割的,会同时启动和敞开,那该怎么让两个容器联动起来呢?
这里就要用到 docker compose
,通过一个 YAML
文件,能够同时启动和敞开两个容器,或者叫一组相干容器。
- 在我的项目的根目录下创立一个
docker-compose.yml
文件,跟最开始的Dockerfile
同一目录下。 - 文件内容如下:
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:
- 删除方才创立的
getting-started
和mysql
两个容器。 - 在我的项目根目录下运行如下命令启动这组容器:
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
留神到 volume
和 network
都创立了,即便 network
没有指定。这是因为默认状况下,compose
会创立一个公共的 network
。
- 接着能够用
docker-compose logs -f
命令看下日志。 - 刷新下浏览器,当初能够失常应用了。而后能够察看下
docker-desktop
面板,能够看到两个容器放在了一起。 - 而后能够通过
docker-compose down
命令或者间接在面板上点击敞开这组容器。
总结
因为要搭建环境,将 docker
官网的内容整顿简化,记录出