Docker入门实践

540 阅读7分钟

基础知识

什么是docker

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。Docker 可以将应用以集装箱的方式进行打包,通过镜像的方式可以实现在不同的环境下进行快速部署,在团队中还可实现一次打包,多次共享。我们在本地将编译测试通过的程序打包成镜像,可以快速的在服务器环境中进行部署,有时也能解决不同的开发环境造成的问题。

镜像

镜像是一个可执行包,Docker 会把应用程序及依赖打包进镜像(Images)里,提供了容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等),通过这个镜像文件可生成 Docker 容器。镜像有两种:基础镜像和个人镜像。基础镜像由各大厂商提供,比如ubuntu镜像,node镜像。个人镜像则是由个人开发者构建上传。有个docker仓库:hub.docker.com/search?q=&t…

容器

容器是镜像的可运行实例,在默认情况下,容器与其它容器及其主机是隔离的,拥有自己的独立进程空间、网络配置。容器直接运行到宿主机上,没有自己的内核。

docker和虚拟机区别

虚拟机是相当于整个操作系统,在这个操作系统上安装和运行软件,资源占用大,开机启动慢。而docker只有需要用到的资源,并不是一个完整的操作系统。容器直接运行到宿主机上,没有自己的内核,没有虚拟硬件。每个容器内都有一个属于自己的文件系统,互不影响。

image.png

image.png

数据卷

-v 宿主机文件位置:容器内文件位置 (类似-p) 绝对路径,相对路径会报错

image.png

image.png

image.png image.png 测试1 /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

image.png

测试2

image.png

image.png 具名和匿名挂载 只写一个是 容器内的位置

image.png

image.png

image.png

image.png

image.png

lALPBGKodgy1XOTNAgDNAv0_765_512.png 数据卷共享是拷贝的,所以一个容器被删除了,其他容易的数据还会在。 lALPBGY19LF_jWLNAbbNAtw_732_438.png

image.png

1626014413966_ADDF62DA-93C1-4c03-87FF-3F2AFA84337C.png

常用命令

抓取 image 文件到本地,去docker官方提供的镜像库去抓取。

docker image pull hello-world

查看 image 文件列表

docker image ls

运行 image 文件,

 docker container run hello-world

执行 docker container run 命令会生成一个正在运行的容器实例,另外 docker container run 发现本地没有指定的 image 文件,其自身还有自动抓取 image 文件功能,就是上面讲解的 docker image pull 命令.

查看正在运行的容器列表

docker ps
或者
docker container ls

查看所有创建过的容器(运行或者关闭)

docker ps -a

初识DockerFile

//docker build 构造镜像,-f 路径名 通过什么文件来构造,-t 构造的镜像名, .生成在当前目录下
// 通过这个命令就可以生成自己的可运行的镜像。(生成了自己的centos镜像)
 docker build -f dockerfile1 -t /liping/centos .

这个每个命令都是镜像的一层 image.png

image.png

image.png 匿名挂载的卷,找到宿主机的位置: docker inspect 容器id

image.png

Dockerfile 的编写命令

image.png

注:CMD 在docker run 时运行。RUN 是在 docker build。

镜像搜索

 docker search nginx

镜像拉取

docker pull nginx

发布镜像实现共享

1、登陆 Docker,已登陆的可以忽略这一步

docker login

2、为本地镜像打标签,tag 不写默认为 latest

 docker image tag [imageName] [username]/[repository]:[tag]

3、发布镜像文件

docker image push [username]/[repository]:[tag]

docker构建nodejs镜像

新建hello-docker目录,新建app.js

const http = require('http')
const PORT = 3000
const server = http.createServer((req,res) => {
    res.end('hello docker')
})
server.listen(PORT,() =>{
    console.log('running---',PORT)
})

同级新建 package.json

{
"name":"hello-docker",
"version":"1.0.0",
"description":"",
"author": "May",
"main":"app.js",
"scripts": {
    "start": "node app.js"
},
"dependencies":{}
}

同级新建Dockerfile

#基础镜像
FROM node:10.0

# 定位到容器的工作目录
RUN mkdir -p /usr/src/nodejs

# 在容器中创建一个目录
WORKDIR /usr/src/nodejs

#Dockerfile 中的每条指令都会创建一个镜像层,Dockerfile 指令或复制的项目文件在没有修改变动的情况下,每个镜像层是可以被复用和缓存的。
# RUN/COPY 是分层的,package.json 提前,只要没修改,就不会重新安装包
COPY package.json /usr/src/nodejs/package.json
RUN cd /usr/src/nodejs/
RUN npm i
# 把当前目录下的所有文件拷贝到 Image 的 /usr/src/nodejs/ 目录下
COPY . /usr/src/nodejs/

EXPOSE 3000
CMD npm start

上面如果按照下面这么写,那么每一次重新构建镜像,都需要下载一次npm包!要充分利用docker缓存

COPY . /usr/src/nodejs/
RUN npm i

构建hello-docker镜像,执行命令docker image build -t hello-docker .

-t 参数用来指定镜像的文件名称,最后一个 . 也不要省略,表示 Dockerfile 文件的所在目录,镜像跑起来的时候会逐一往下执行Dockerfile文件里面的命令

image.png 执行以上命令之后,我们来查看下新生成的镜像文件 hello-docker。 使用命令docker image 或者在docker桌面应用程序中就可以看到新生成的镜像文件 hello-docker

image.png

运行容器

镜像构建成功之后通过 docker container run 命令来生成一个容器,让镜像跑起来,

docker container run -d -p 3001:3000 hello-docker

image.png

-d:表明容器的运行模式在后台,守护式运行(没有交互式会话,长期运行,适合运行应用程序和服务)

-it 交互式运行。只有输入exit才退出终端,退出终端后,容器仍然在后台运行。

-p:端口映射,将本机的 3000 端口映射到容器的 3001 端口,这样在外网就可通过 30001 端口访问到我们的服务。为什么要映射端口?因为Docker里每个容器都是相对独立的,拥有自己的内部ip。容器里运行的一些网络应用,要让外部也可以访问,就需要将端口映射到宿主机上。

hello-docker:为我们的镜像名字

可以看到新增的容器:

image.png

此时我们的 Node.js 服务已经运行在 Docker 容器的虚拟环境里了,curl http://localhost:30001 可以进行测试

image.png

检查日志

image.png

4ffceef152f4 为容器 ID,执行命令docker logs -f 4ffceef152f4

image.png

更进一步 动态设置环境变量

在原来hello-docker项目中,修改package.json

image.png

app.js

image.png

dockerfile

image.png 可构建一个 Docker 镜像

docker image build . -t lp/hello-docker

运行镜像

docker run -d -p 3000:3002 lp/hello-docker

按照上面 CMD npm run dev 这样写死只能打包一种环境。

修改dockerfile

image.png

image.png

构建镜像,传入环境变量

docker build --build-arg node_env=dev . -t lpp/hello-docker

运行

docker run -d -p 3002:3003 lpp/hello-docker

查看日志

image.png

image.png

再更进一步

在项目中, 新建dockerfile

#使用基础镜像库
FROM nginx

#创建工作路径
RUN mkdir -p /data/web/
# 切换到data/web/目录
WORKDIR /data/web/

# 将当前的dist目录拷贝到容器的/data/web/
COPY ./dist/  /data/web/
COPY nginx.template /tmp/

# 启动nginx,关闭守护式运行,否则容器启动后会立刻关闭 docker run 的时候命令行输入的环境变量参数会在这边被替代 传入nginx.template 
CMD envsubst '$API_URL $POINT_URL'  < /tmp/nginx.template > /etc/nginx/nginx.conf && nginx -g "daemon off;"

package.josn中新增docker命令,复制Nginx.template到tmp目录

image.png 在script目录下新建docker_run.sh 设置环境变量

image.png

执行npm run docker ,就会执行docker_run.sh里的语句,docker服务就跑起来了。 从docker桌面打开运行终端

image.png

image.png

我们项目里面的nginx.template内容原封不动地复制到tmp文件夹下

查看/etc/nginx/nginx.conf 中的内容 此时nginx.conf是以nginx.template为模板 并且里面的环境变量被替换了,就可以看到实际生效的nginx配置文件。 image.png

image.png

image.png

参考

jartto.wang/2020/07/04/…

mp.weixin.qq.com/s/S7ksqF8z4…