Docker基本使用

665 阅读10分钟

通过这篇文章大概可以了解到的内容有:

  • 什么是Docker
  • Docker常见命令
  • Dockerfile

Docker简介

Docker是什么

Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用及依赖环境到一个可移植的容器中,然后发布到任何运行有Docker引擎的机器上。它集版本控制、克隆继承、环境隔离等特性于一身,提出一整套软件构建、部署和维护的解决方案,可以非常方便地帮助开发人员,让大家可以随心所欲地使用软件而又不会深陷到环境配置中。

为什么使用Docker

以前部署一个应用程序,不管是在一个物理机还是虚拟机上,都需要安装一大推依赖的软件,比如说NginxMySQLRedis等,并且需要修改一些配置文件;而使用Docker只需要编写Dockerfile文件,然后把这些依赖及应用打包成一个镜像后就可以随时随地的运行了。

Docker使用容器引擎解决平台依赖问题,它在每台宿主机上都启动一个Docker的守护进程,而守护进程屏蔽了与具体平台相关的信息,对上层应用提供统一的接口,因此Docker应用可以在多个平台下运行,具有环境隔离和可移植的特点。

镜像、容器和虚拟机

说到Docker,不得不提镜像和容器。可以简单理解为:镜像类似于手机应用上的安装包,容器相当于APP,DocerHub等镜像仓库相当于应用商店。

其实Docker镜像就是一个分层的文件系统,其中包含应用程序运行时所需的代码、依赖和配置等;而容器就是在镜像的最上层加一层读写层

容器其实就是一个进程,可以通过docker container top 容器ID查看容器运行的进程,通过ps -aef --forest发现有个进程其实就是容器运行的进程

1651658211(1).png

下面是一张容器和虚拟机的区别

image.png (注:该图片来自于网络)

Docker安装

Docker的安装非常简单,只要参考官方文档一步一步执行命令即可,例如这里安装在ubuntu系统中。

  1. 如果之前有安装过的,需要先卸载之前的版本
$ sudo apt-get remove docker docker-engine docker.io containerd runc
  1. 更新apt-get并安装一些工具
$ sudo apt-get update

$ sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

3.添加Docker提供的官方密钥

 $ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  1. 安装Docker Engine
 $ sudo apt-get update
 $ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
  1. 可以通过docker --version查看是否安装成功

其它系统的安装教程可以查看Docker官方的安装教程

Windows系统安装Docker需要先安装一个WSL环境, WSL的安装教程可以参考WSL的安装教程, 另外一般配合Windows Terminal使用, 🤔emm...,Windows安装Docker会稍微比较麻烦一点,而且查看Docker Bridge网络的时候,一些Linux工具就无法使用了,所以尽量用Linux环境去使用Docker。

这里再推荐一个vscode Remote Development插件,它可以方便远程连接到Linux服务器,然后做一些文件的编辑和命令执行等。

image.png 它内置了Remote - SSH, Remote - WSL, Remote - Container三个插件,因此使用这个插件可以连接到Linux、WSL或Linux中的容器

Docker常用命令

image相关的命令

微信截图_16529524533140.png

可以使用docker image --help查看镜像相关命令

  • docker image build: 构建Dockerfile镜像,格式为docker image build [OPTIONS] PATH | URL | -, 例如docker image build -f Doickerfile-nginx -t mynginx:1.0.0 ., -f可以指定文件,-t指定镜像名称和tag, .表示当前路径
  • docker image history: 查看镜像的构建历史,格式为docker image history [OPTIONS] IMAGE, 例如docker image hisotory ubuntu:21.10
  • docker image import: 从文件或者URL中导入镜像文件,格式为docker image import [OPTIONS] file|URL|- [REPOSITORY[:TAG]], 例如docker image import https://example.com/exampleimage.tgz
  • docker image inspect: 查看镜像详细信息,格式为docker image inspect [OPTIONS] NAME|ID [NAME|ID..., 例如docker image inspect ubuntu:21.10
  • docker image load: 导入镜像文件,格式为docker image load [OPTIONS], 例如docker image load --input fedora.tar
  • docker image ls: 列出镜像
  • docker image prune: 移除没有使用的镜像
  • docker image pull: 拉取镜像
  • docker image push: 推送镜像
  • docker image rm: 删除镜像 其中最为重要的命令为docker image build

container相关命令

可以使用docker container --help查看容器的相关命令

常见的有:

  • docker container attach: 连接到容器
  • docker container commit: 从容器中创建一个镜像
  • docker container create: 从镜像中创建一个容器
  • docker container run: 创建容器并运行,格式为docker container run [OPTIONS] IMAGE [COMMAND] [ARG...], 例如docker run --name=nginx -d -p 90:80 -v /home/nginx:/usr/nginx/html nginx , --name可以指定容器名称,-d表示运行在后台, -p指定端口映射,表示宿主机90的端口映射到容器80的端口,-v可以将容器的目录绑定到宿主机上的目录
  • docker container exec;进入到容器环境,格式为docker container exec [OPTIONS] CONTAINER COMMAND [ARG...], 例如docker container exec -it nginx sh, -it表示以交互式的方式进入到容器中,sh表示使用的终端
  • docker container start: 启动容器
  • docker container restart: 重启容器
  • docker container stop: 停止容器
  • docker container rm: 删除容器

volume相关命令

volume可以理解为数据的卷轴,用来将容器的数据挂载到宿主机中,防止容器销毁掉导致数据丢失的问题。常见的应用场景是挂载数据库的文件

可以使用docker volume --help 查看volume的命令

  • docker volume create: 创建一个数据卷
  • docker volume inspect: 查看数据卷的详细信息
  • docker volume ls: 列出数据卷
  • docker volume prune: 删除没有使用的数据卷

network相关命令

Docker网络相关的命令同样可以使用docker network --help的方式查看

  • docker network connect: 连接容器到一个网络
  • docker network create: 创建docker网络。例如创建一个名字为mybridge,网关为172.200.0.1,子网为172.200.0.0/16的网络docker network create -d bridge --gatway 172.200.0.1 --subnet 172.200.0.0/16 mybridge
  • docker network disconnect: 断开容器上的网络连接
  • docker network ls: 列出docker网络
  • docker network inspect: 查看某个网络详情
  • docker network prune: 移除没有使用的网络
  • docker network rm: 删除网络

总结

上面只是列出比较常见的Docker命令行工具,有些命令可以使用简写的形式,例如上面的docker image build可以简写为docker build。重点强调的有三个命令是最最最常用的,也是最重要的三个命令

  • docker build
  • docker run
  • docker exec 如果平时忘记哪个命令,可以使用docker --help查看所有的Docker命令行工具,也可以通过文档的形式查看命令的详细用法docs.docker.com/engine/refe…

Dockerfile

Docker镜像获取,一般可以从Docker仓库中获取,也可以通过镜像文件导入的方式获取,另外程序部署当中最为常用的还是通过Dockerfile文件的形式构建镜像。

Dockerfile指令

  • FROM: 指定所创建镜像的基础镜像,如果本地不存在,则默认会去Docker Hub下载指定的镜像,例如
FROM node:14

任何Dockerfile文件中的第一条指令必须为FROM指令,如果同一个Dockerfile文件中指定创建多个镜像,可以使用多个FROM指令

  • WORKDIR: 指定工作目录,行为相当于Linux的cd命令切换工作目录,但是与cd命令不同的是,如果指定的工作目录不存在,则会自动创建,例如
WORKDIR /home/code
  • RUN: 运行指定的命令。例如
RUN apt-get update
RUN apt-get install -y wget
  • COPY: 复制宿主机的source目录到镜像的target目录中,目录不存在时,会自动创建。例如
COPY . /home/code/
  • ADD: 将指定的source目录、URL或压缩文件添加到容器的source目录中。例如
ADD package.json .
  • ARG: 声明变量,ARG声明的变量仅存在于镜像的构建阶段中,并且可以在镜像构建的时候使用--build-arg的参数取代Dockerfile中定义的变量

  • ENV: 声明变量,ENV声明的变量不仅存在于镜像的构建节点,而且存在于镜像构建后的容器中。例如

ENV NAME=docker
CMD echo "hello $NAME"
  • EXPOSE: 声明镜像内服务所监听的端口,例如
EXPOSE 80
  • CMD: 指定启动容器时默认执行的命令。需要注意的是一个Dockerfile文件中只能有一个CMD命令,如果指定了多条CMD命令,则只有最后一条会执行

  • ENTRYPOINT: 指定容器启动时的命令。但是与CMD指令不同的是,它所设置的命令是一定会执行的,而CMD指令可以在docker run时传入其它命令,从而覆盖掉原本Dockerfile文件所设置的命令。两者可以配合使用,ENTRYPOINT设置执行的命令,CMD传递参数,例如

# Dockerfile-both
FRON ubuntu:21.04
ENTRYPOINT ["echo"]
CMD []

然后通过docker image build -f ./Dockerfile-both -t demo-both .创建一个demo-both:latest的镜像,然后执行docker container run -it demo-both hello worldhello world传递给CMD,可以在终端中看到打印的hello world

说明CMDENTRYPOINT指令都支持shell格式和exec格式
shell 格式

CMD echo "hello world"

ENTRYPOINT echo "hello world"

exec格式

CMD ["echo", "hello world"]

ENTRYPOINT ["echo", "hello world"]

需要注意的是,如果执行时有带参数或者变量的时候,使用shell格式和exec格式有点区分,例如

# shell 格式
FROM ubuntu:21.04
ENV NAME=docker
CMD echo "hello $NAME"

# exec格式
FROM ubuntu:21.04
ENV NAME=docker
CMD ["sh","-c","echo hello $NAME"]
  • VOLUME: 创建数据挂载卷,例如VOLUME ["data]

Dockerfile实例

一个Dockerfile文件可以创建一个镜像,也可以创建多个镜像。

  1. 单阶段构建 这里随便用umi脚手架创建一个umi项目,然后在工作目录中编写Dockerfile文件,例如
FROM node:14

WORKDIR /home/code
ADD . /home/code
RUN npm config set registry 'https://registry.npm.taobao.org' && npm install -g http-server && npm install && npm run build

EXPOSE 80

CMD http-server ./dist -p 80

执行docker image build -t umiapp .创建镜像
执行docker container run -d -p 80:80 --name umiapp umiapp创建并运行容器

  1. 多阶段构建
FROM node:14 as builder

WORKDIR /home/code
COPY package.json /home/code
RUN npm config set registry 'https://registry.npm.taobao.org' && npm install
ADD . /home/code
RUN npm run build

FROM nginx:alpine
COPY --from=builder /home/code/dist /usr/share/nginx/html

EXPOSE 8000

执行docker image build -t umiapp .创建镜像
执行docker container run -d -p 80:80 --name umiapp umiapp创建并运行容器

在需要编译成可执行文件的程序中,一般都是用多阶段构建(例如Go, Java等程序)。因为程序本身的体积是比较小的,而编译环境的体积往往是比较大的,利用多阶段构建可以构建程序,可以有效减少应用的体积大小。
下面是Go程序的多阶段构建的dockerfile

# syntax=docker/dockerfile:1

##
## Build
##
FROM golang:1.16-buster AS build

WORKDIR /app

COPY go.mod ./
COPY go.sum ./
RUN go mod download

COPY *.go ./

RUN go build -o /docker-gs-ping

##
## Deploy
##
FROM gcr.io/distroless/base-debian10

WORKDIR /

COPY --from=build /docker-gs-ping /docker-gs-ping

EXPOSE 8080

USER nonroot:nonroot

ENTRYPOINT ["/docker-gs-ping"]

在实际应用中,如果不知道怎么写Dockerfile,可以在网上搜索相关类型的Dockerfile,然后结合项目进行修改

编写Dockerfile的注意事项

如果编写的Dockerfile文件中没有注意细节的话,有可能导致镜像太大,然后下载部署就需要花费很多事件。下面简单列举一些能有效减少体积或加快依赖安装的方法。

  1. 减少镜像文件分层:在Dockerfile文件中,RUN, ADD, COPY指令会增加镜像分层,可以通过合并指令的方式减少镜像文件分层,例如
RUN npm install
RUN npm build

# 优化为
RUN npm install && npm build
  1. 利用缓存: 通常把不容易变化的指令放在前面执行,因为前面的指令发生变化,会影响到后面指令

  2. 编写.dockerignore文件: .dockerignore文件类似于.gitignore文件,在镜像构建的时候忽略一些对程序运行不影响的文件,来减少镜像的体积

  3. 选择体积较小的基础镜像:一般alpine版本的基础镜像相对于某个特定版本的基础镜像要小很多,例如node:14-alpinenode:14要小三百多兆

企业微信截图_16532687181121.png

image.png

  1. 对于前端镜像打包来说,个人总结有一些优化
  • 一般上传package-lock.json文件或者yarn.lock文件,然后用npm ci下载依赖包
  • 使用淘宝镜像源或者私服替代官方源下载
  • 使用npm install --production下载依赖

参考链接

Docker官方文档