1、容器镜像
应用下载地址:https://docs.docker.com/get-started/02_our_app/
1.1、创建容器镜像
- 创建Dockerfile文件(注意不要有txt文件扩展名,可能会导致后续错误),如下内容
FROM node:12-alpine
RUN apk add --no-cache python g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
- 使用Dockerfile来创建一个容器镜像,命令行进入Dockerfile文件同级目录,在当前目录查找Dokerfile文件然后在创建容器镜像
sir-2:app x$ docker build -t getting-started .
1.2、运行容器
现在我们可以运行一个上节创建的容器镜像(getting-started),
# -dp 以detached模式(在后台)运行新容器并创建主机和容器之间的端口映射
sir-2:app x$ docker run -dp 3000:3000 getting-started
1.3、更新应用
编辑应用之后需要先停止以前的同端口应用,
- 获取容器ID
sir-2:app x$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
99d4e2982766 getting-started "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp funny_northcutt
sir-2:app x$
- 通过获取的Container id来停止容器,restart为重启容器
sir-2:app x$ docker stop 99d4e2982766
99d4e2982766
sir-2:app x$
- 一旦容器停止,就可以移除容器
sir-2:app x$ docker rm 99d4e2982766
- 编辑应用后,重新打包后运行
sir-2:app x$ docker build -t getting-started .
...
sir-2:app x$ docker run -dp 3000:3000 getting-started
1.4、持久化数据:container volume
- 创建volume
sir-2:app x$ docker volume create todo-db
todo-db
sir-2:app x$
- 运行挂载volume的容器
# -t 指定挂载volume
sir-2:app x$ docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
2d7eda85ef64ef2d746eb121083c86dc7b45bd0c84f4e584bf0a9f74f49c0d23
sir-2:app x$
- 验证:添加数据,然后停止删除应用,开启一个新的容器从同一个镜像,可以得到同样的以前的数据。
- 查看数据存放的地方
sir-2:app x$ docker volume inspect todo-db
[
{
"CreatedAt": "2021-06-21T08:01:53Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": null,
"Scope": "local"
}
]
sir-2:app x$
1.5、–link
docker run --link可以用来链接2个容器,使得源容器(被链接的容器)和接收容器(主动去链接的容器)之间可以互相通信,并且接收容器可以获取源容器的一些数据,如源容器的环境变量。
1.6、Use Bind Mount
a dev-mode container
- 先关闭上面创建的容器
# -dp 3000:3000 - detached (后台)模式运行并创建端口映射
# -w /app - 设置工作目录
# -v "$(pwd):/app" - volume挂载宿主机的当前目录到容器的/app(格式:宿主机目录:镜像内挂载目录),挂载后容器内就可以共享宿主机里的文件。
# node:12-alpine - 使用的镜像,Note that this is the base image for our app from the Dockerfile
# sh -c "yarn install && yarn run dev" - the command. We’re starting a shell using sh (alpine doesn’t have bash) and running yarn install to install all dependencies and then running yarn run dev. If we look in the package.json, we’ll see that the dev script is starting nodemon.
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
node:12-alpine \
sh -c "yarn install && yarn run dev"
- 利用container id来查看日志,container id可以通过docker ps获取
sir-2:app x$ docker logs -f 6731b0c8ade0
yarn install v1.22.5
[1/4] Resolving packages...
success Already up-to-date.
Done in 0.34s.
yarn run v1.22.5
$ 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.7、Container Networking
**注意:**如果两个容器在同一个网络,就可以互相通信,否则不能。
- 创建网络
sir-2:app x$ docker network create todo-app
- 创建MySQL容器,并依附到上面的网络,并定义MySQL初始化需要的变量
注意:如果使用一个已经包含数据库的数据目录启动容器,则所有环境变量都不会生效
# -v todo-mysql-data:/var/lib/mysql - 名为todo-mysql-data的vaolume如果不存在会自动创建,挂载到/var/lib/mysql。
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
- 查询MySQL的container id,确认MySQL正确运行,连接数据库并验证连接,
sir-2:app x$ docker exec -it 4f085a0d05c3 mysql -u root -p
- 使用nicolaka/netshoot镜像创建容器,并连接到同一个网络
sir-2:app x$ docker run -it --network todo-app nicolaka/netshoot
dP dP dP
88 88 88
88d888b. .d8888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P
88' `88 88ooood8 88 Y8ooooo. 88' `88 88' `88 88' `88 88
88 88 88. ... 88 88 88 88 88. .88 88. .88 88
dP dP `88888P' dP `88888P' dP dP `88888P' `88888P' dP
Welcome to Netshoot! (github.com/nicolaka/netshoot)
6d04e2c399cd ~
- 使用dig查询mysql的IP地址
6d04e2c399cd ~ dig mysql
; <<>> DiG 9.16.11 <<>> mysql
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16449
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;mysql. IN A
;; ANSWER SECTION:
mysql. 600 IN A 172.18.0.2
;; Query time: 1 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Mon Jun 21 09:12:52 UTC 2021
;; MSG SIZE rcvd: 44
6d04e2c399cd ~
- 运行MySQL和APP
sir-2:app x$ 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"
- 访问localhost:3000,然后添加数据,通过MySQL的container id验证数据是否被插入到数据库中
sir-2:app x$ docker exec -it container-id mysql -u root -p
1.8、Docker Compose
通过创建docker-compose.yml文件可以定义和共享多容器应用程序的工具
- 在项目根目录下创建docker-compose.yml,内容如下
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:
- 运行
sir-2:app x$ docker-compose up -d
Docker Compose is now in the Docker CLI, try `docker compose up`
Creating network "app_default" with the default driver
Creating volume "app_todo-mysql-data" with default driver
Creating app_mysql_1 ... done
Creating app_app_1 ... done
- 测试完毕,结束所有应用
sir-2:app x$ docker-compose down
Stopping app_app_1 ... done
Stopping app_mysql_1 ... done
Removing app_app_1 ... done
Removing app_mysql_1 ... done
Removing network app_default
sir-2:app x$