在公司使用微服务以后,由于各个服务之间有依赖关系,调试本身服务的时候每次都须要编译运行其余服务,原来使用一台开发机做为开发环境的方式就很麻烦,因此考虑用 docker
部署一套能够复用的开发环境。首先了解下docker
的基本使用。html
点击连接下载 docker-desktop ,而后傻瓜式安装。node
安装好以后能够在命令行执行 docker --version
命令,查看 docker
是否正常运行。python
官方确定有教程的,因此能够去官网找一下,我这边看的是 docker/getting-started
的教程。docker/getting-started
自己就是一个 docker
的 repo
。下面说一下怎么看这个教程。mysql
在安装好 docker
以后,在命令行运行 docker run -d -p 80:80 docker/getting-started
命令, 而后就启动了一个容器。sql
而后本地浏览器访问 http://localhost/tutorial/
能够看到教程。英文的,可是很好理解,有点英语基础均可以看懂。本篇教程也是按照这个教程来的,记录下方便之后本身用。docker
接下来只讲使用,不讲原理。shell
教程提供了一个 Node.js
的应用让咱们直接使用,点击下载 Node.js APP , 本地的链接,上述步骤没作下载不下来。数据库
将下载的 zip 文件解压,用编辑器打开, 这边我用的是 vscode
。浏览器
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
文件。网络
docker run
命令启动一个容器,启动的时候要指定使用刚才构建的镜像。命令以下:docker run -dp 3000:3000 getting-started
todo list
应用。你如今能够看下下载的 docker-desktop
面板,里面有两个容器,一个是用来看教程的,一个是新建立的本身的 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
找到全部启动的容器。以下图:docker rm <the-container-id>
命令删除该容器。docker run -dp 3000:3000 getting-started
docker
中每一个容器的文件系统都是独立的,一个容器没法访问到另外一个容器的文件。同一个容器,再重启后旧容器中的文件就丢了。因此上面的 todo list APP
再容器更新后以前加的 todo
就没了。那怎么让容器更新后还能访问到以前的数据呢?
这里引出容器的 volumes
概念。 volumes
会将容器内的目录映射到宿主机的目录上,而后每次启动的时候都加载宿主机的目录,文件就不会丢了。
有两种类型的 volumes
,一种是 named volumes , 另外一种是 bind mounts 。
首先讲一下 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
的意思。
todo
。APP
容器,从新启动一个。todo
没有丢。注:查看
Valumes
信息命令:docker volume inspect <valumes name>
而后再来讲一下 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"
:运行 shelldocker 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'}
该 todo list APP
以前用的是 SQLite Database 来做为存储的。如今使用个更通用的,好比 MYSQL
。 固然能够直接把 MYSQL
跟 APP
部署到同一台机器上,可是 docker
不建议这么作。 docker
但愿每一个容器内的功能单一。因此如今的部署方案是两个容器,一个部署 MYSQL
,一个部署 APP
。 像这样:
这样两个容器之间须要经过网络链接。这样就引出 network 概念。同一个 network 上的容器能够相互通讯。
docker network create todo-app
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)
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
todo
。mysql
:docker exec -it <mysql-container-id> mysql -p todos
运行以下命令查看是否有新增的数据:
mysql> select * from todo_items;
启动了 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
官网的内容整理简化,记录出