docker与容器管理

为什么选择docker

参考官方文档:https://docs.docker.com/get-started/overview/#what-can-i-use-docker-for

容器管理

Dockerfile

下面代码是一个镜像的Dockerfile文件,对里面的内容做一个简单的介绍

# FROM + 基础镜像,新镜像基于该镜像进行定制
FROM node:12-alpine    # WORKDIR指定容器内工作目录
WORKDIR /usr/src/app# ARG/ENV 设置环境变量,方便后续调用
ARG NODE_ENV
ENV NODE_ENV $NODE_ENV# COPY 将当前目录或文件复制到容器工作目录下
COPY package.json /usr/src/app/# RUN build过程中需要执行的命令
RUN npm install --registry=https://registry.npm.taobao.org
COPY . /usr/src/app# CMD ,在docker run时执行的命令,dockerfile中只能有一个CMD
CMD [ "npm", "start" ]ENV BIND_HOST 0.0.0.0
ENV BIND_PORT 3600

开始build镜像

➜ docker build -f=Dockerfile -t=test:0.1 .
Sending build context to Docker daemon  54.93MB
Step 1/10 : FROM node:12-alpine
12-alpine: Pulling from library/node
cbdbe7a5bc2a: Pull complete
091983d60f65: Pull complete
7bacc183740f: Pull complete
c4a5a5d270d4: Pull complete
Digest: sha256:9623cd396644f9b2e595d833dc0188a880333674488d939338ab5fde10ef7c43
Status: Downloaded newer image for node:12-alpine---> 18f4bc975732
Step 2/10 : WORKDIR /usr/src/app---> Running in b68feb1e9228
Removing intermediate container b68feb1e9228---> ee7553e2086e
Step 3/10 : ARG NODE_ENV---> Running in 5554f8f5cb85
Removing intermediate container 5554f8f5cb85---> f277df808e93
Step 4/10 : ENV NODE_ENV $NODE_ENV---> Running in 275d18fa60ce
Removing intermediate container 275d18fa60ce---> e35632cba70c
Step 5/10 : COPY package.json /usr/src/app/---> 0e7abb2cf497
Step 6/10 : RUN npm install --registry=https://registry.npm.taobao.org---> Running in be71b8114612
npm WARN deprecated chokidar@2.1.8: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated> nodemon@1.19.4 postinstall /usr/src/app/node_modules/nodemon
> node bin/postinstall || exit 0Love nodemon? You can now support the project via the open collective:> https://opencollective.com/nodemon/donatenpm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN ohif-redir@1.0.0 No description
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})added 486 packages from 336 contributors in 8.447s4 packages are looking for fundingrun `npm fund` for detailsRemoving intermediate container be71b8114612---> b89634a00e5b
Step 7/10 : COPY . /usr/src/app---> ab58cc1736a5
Step 8/10 : CMD [ "npm", "start" ]---> Running in 85ddfbda7da8
Removing intermediate container 85ddfbda7da8---> 10af46858c98
Step 9/10 : ENV BIND_HOST 0.0.0.0---> Running in 9b45c37476af
Removing intermediate container 9b45c37476af---> 3e78c49f0b08
Step 10/10 : ENV BIND_PORT 3600---> Running in 48e86d2b434c
Removing intermediate container 48e86d2b434c---> 9d592c0d4e20
Successfully built 9d592c0d4e20
Successfully tagged test:0.1

查看镜像,并简单run一下

➜  docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test               0.1                 9d592c0d4e20        29 seconds ago      197MB
node                12-alpine           18f4bc975732        3 weeks ago         89.3MB➜ docker run   --name test -d test:0.1 
e9ef5382af65b8f9f4a9b2019310313a430b1113bd3ef326ad18497b1f2fe297➜  docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
e9ef5382af65        test:0.1           "docker-entrypoint.s…"   6 seconds ago       4 minutes ago                            test➜ docker logs -f test
> test@1.0.0 start /usr/src/app
> node index.jsServer listening at http://0.0.0.0:3600

容器就可以这样简单的跑起来,但是实际情况中,还存在很多变量引用,以及其他容器间的联系,比如下面这个yml文件,可以看到存在一部分变量,在实际生产环境中,只有根据实际情况正确引入这些变量,才能将整个产品搭建起来

test:image: test:2.1.0restart: alwaysports:- 3600:3600volumes:- ./log-test:/usr/src/app/logenvironment:- PAC_URL=http://${SERVER_IP}:5000- VIEWER_URL=http://${SERVER_IP}:${VIEWER_PORT}/viewer- IOS_URL=http://ios:6527/api- REDIS_HOST=redis- REDIS_PORT=6379logging: *id001
由于上面的变量都是单个定义的,所以单独运行时有两种方式定义和引用这些变量
# 一种是需要将这些变量提前写入环境变量中,启动是调用,如下
export PAC_URL=http://192.168.3.2:5000
export VIEWER_URL=http://192.168.3.2:3000/viewer➜  docker run -e PAC_URL  --name test1 -d test:0.1
d2dde1d2ab48fe85125287d19597bde9eed009def3ab97107dd66e2cc9b48f9d# 另外一种是直接在命令中引用
➜  docker run -e PAC_URL=http://192.168.3.2:5000  -e VIEWER_URL=http://192.168.3.2:3000/viewer  --name test3 -d test:0.1
026c230ca36117de1f1e23a37ee807b24c3b8ecf341708bca800a91d4fd7c0fe➜  docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
026c230ca361        test:0.1           "docker-entrypoint.s…"   2 minutes ago       Up 2 minute                             test3
d2dde1d2ab48        test:0.1           "docker-entrypoint.s…"   3 minutes ago       Up 3 minutes                            test1
e9ef5382af65        test:0.1           "docker-entrypoint.s…"   9 minutes ago       Up 9 minutes                            test

可以看到,如果这么做,在多容器的产品中,部署运维是非常麻烦的,为了解决整个问题,引入了docker-compose进行多容器的管理,简单介绍下常用的几个配置

version: '2.3'services:test:image: test:2.1.0restart: alwaysports:- 3600:3600volumes:- ./log-test:/usr/src/app/logenvironment:- PAC_URL=http://${SERVER_IP}:5000- VIEWER_URL=http://${SERVER_IP}:${VIEWER_PORT}/viewer- IOS_URL=http://ios:6527/api- REDIS_HOST=redis- REDIS_PORT=6379ipc: hostlogging: &id001driver: json-fileoptions:max-size: 10mmax-file: '10'

version

docker-compose.yml对应的compose版本,比如上述yml中,使用的是2.3,不同版本对应的语法有差异,因此该内容不能随意更改

ports

容器的端口映射,拿上面test举例,默认是3600,假如一些特殊情况只能给我们开放3601端口,就可以在该配置中修正,其中冒号(:)前面的是对外端口,后面的是默认端口

➜  docker run  -p 3601:3600/tcp -e PAC_URL   --name test2 -d test:0.1
b05b88d04f9e3a177c28f9379b5a69cf18a1c5ebe5dd60c080518c3b6e1688da➜ docker ps -a                                                                           
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
b05b88d04f9e        test:0.1           "docker-entrypoint.s…"   10 minutes ago      Up 10 minutes       0.0.0.0:3601->3600/tcp   test2

volumes

docker是一种虚拟化技术,container(容器)启动后,容器内部各种进程启动并按照编写内容工作,容器结束后(down)里面的内容会恢复初始的样子,类似与阅后即焚.

但实际生产中,我们必须要保证运行后产出的留存,拿我们的产品举例,数据发送后处理并生产的结果,这些都是在容器内部进行的,这些结果不能随着容器的关闭而消失

既然容器内部数据会随着容器生命周期消失,那么我们就只能将数据存储在宿主机上,即运行容器的机器上,也就是我们的服务器中,这种方式我们称之为数据持久化

volume 是docker数据持久化方式之一,可以使用 docker volume ls 查看对应的存储,通过inspect命令来查看volume的信息,可以看到一个Mountpoint,即数据在宿主机的实际存储路径,同时从名字可以看到,它是通过一种挂载的方式实现的

之后的一些图打了码,各位将就着看吧

然后我们来看一下volume的创建和使用

创建volume

可以通过docker-compose文件创建,可以看到对应volume创建非常简单

通过这种方式,每次启动时会检查是否已经存在对应的volume,不存在则创建,我们可以通过inspect来查看这个volume的详细内容

可以看到,volume详细信息中,和yml文件中内容一致,其中label可以看到,分为project和volume,组合在一起就是volume的名称,当然这个只有通过docker-compose来创建才会默认打上这些内容

➜ docker volume create hello --driver=local
hello
➜ docker volume ls | grep hello
local               hello
➜  docker volume inspect hello
[{"CreatedAt": "2020-08-25T11:22:02+08:00","Driver": "local","Labels": {},"Mountpoint": "/var/lib/docker/volumes/hello/_data","Name": "hello","Options": {},"Scope": "local"}
]

引用volume

创建完毕后,我们就可以使用了,这个就是容器的另外一个特性:即插即用

额外提一下,关于docker-compose中变量的引用问题。yml文件中,${}均为引用,引用.env文件中的值

environment/env_file

environment和env_file两者均为参数的引用,只是一个是单个变量,另外一个是以文件的形式

depends_on

容器见的启动/关闭顺序,比如一个前端应用,depends_on一个数据库,那么启动的时候数据库会先启动,之后前端应用才会启动(仅仅是启动顺序,不是说等前者启动完毕才行)

有时候启动服务会报错,报连不上什么...,就是类似这个启动顺序问题,后者启动了但是前者没有启动或者启动成功,就是报错

logging

通过logging可以定义日志相关信息,比如下图,设置驱动为json-file,每个日志最大为10M,日志文件个数最大为10个,也就是说这个服务最大可以存储100M的日志

模板引用

每个服务都会生成日志,如果我们要求每个服务都和上面一样,即驱动为json-file,每个日志最大为10M,日志文件个数最大为10个,那么我们就需要在每个服务的后面写重复的内容,为了避免这种重复,就有了这种语法,直接引用上面的内容

首先需要定义模板,使用&来定义,然后在后面通过*来引用,当然模板的名字可以自己取,我们现在用的是id001

同样的,定义volume时也可以使用了模板引用,不过这个意义不大,version 2之后,创建volume时driver默认就是local

networks

networks是容器用于控制容器间及容器与宿主机网络通讯的相关设置,docker默认提供多种网络通讯模式,常用的包括

  1. bridge:默认的网络驱动模式,容器间独立通讯
  2. host:容器直接使用宿主机网络

docker安装后,会默认自动创建三个网络

➜ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
202925bdc47c        bridge              bridge              local
9dc28b5e779a        host                host                local
c77b352a65ad        none                null                local查看下bridge的详细信息
➜ docker network inspect bridge
[{"Name": "bridge","Id": "202925bdc47c5c667ec9d02203a4f0e8cf9c3d996bb83d0ff8ca821edb28546d","Created": "2020-08-24T16:58:14.693299541+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "172.17.0.0/16","Gateway": "172.17.0.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {},"Options": {"com.docker.network.bridge.default_bridge": "true","com.docker.network.bridge.enable_icc": "true","com.docker.network.bridge.enable_ip_masquerade": "true","com.docker.network.bridge.host_binding_ipv4": "0.0.0.0","com.docker.network.bridge.name": "docker0","com.docker.network.driver.mtu": "1500"},"Labels": {}}
]

可以看到,如果不指定网络,所有的容器都会在172.17.0.0/16这个网段,由于一些网络冲突问题,我们也可以自定义

在正常运行的服务器上查看网络设置,可以看到我们自定义的network,查看详细信息会看到,每隔容器都会单独占一个对应网段的ip

➜  docker network ls
NETWORK ID          NAME                              DRIVER              SCOPE
fd572b089a49        bridge                            bridge              local
0434375b73ab        pac_default                       bridge              local
7844a7724804        host                              host                local
22355a4e177c        none                              null                local➜  docker network inspect pac_default
[{"Name": "pac_default","Id": "0434375b73ab7b4ffe9b38d77e426d754de24ea14d0d66983727ed86b8f90f91","Created": "2020-08-19T16:14:30.049203895+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "8.8.6.1/24","Gateway": "8.8.6.1"}]},"Internal": false,"Attachable": true,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"00cc8c72f9f94c3af65c73e20114cc68f6dda51982d9716abfc822a5cbd502bf": {"Name": "pac_test_1","EndpointID": "2790000d760a8448e58591a6018ad0712a14a8264365f2466a5f31f749011584","MacAddress": "02:42:08:08:06:13","IPv4Address": "8.8.6.19/24","IPv6Address": ""},"0b7775ba892265b2243297d6ba41cdf18d43c84041801280367c3bfa59864d2c": {"Name": "pac_test2_1","EndpointID": "c734ed02c99fd06910aa561723b19ddb0a6dc346fa1a6e5d2587e6a0c18c14df","MacAddress": "02:42:08:08:06:0b","IPv4Address": "8.8.6.11/24","IPv6Address": ""},"Options": {},"Labels": {"com.docker.compose.network": "default","com.docker.compose.project": "pac"}}
]

Docker小结

上面将基本的docker使用内容都做了简单的介绍,回顾下docker的概念,它是一种虚拟化技术,对进程的一种隔离

多个容器运行在宿主机上,相互之间不影响,就和插座和充电器或者电源线的关系一样。

镜像就是一个插线板,插线板有各种插孔,通了电就是容器,但是要让容器真正发挥作用,还需要插上各种充电器,接上各种电器,运行结果就是保证电器的正常运行或者手机充满了电

一旦插线板断了点,即容器down掉,就恢复了之前的样子,但是产品不变,即之前电器运行,手机充满了电


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部