前端了解这些 Docker 基础操作就够了

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 前端了解这些 Docker 基础操作就够了

应用场景

  • 节省项目环境部署时间

    • 单项目打包
    • 整套项目打包
    • 新开源技术
  • 环境一致性
  • 持续集成
  • 微服务
  • 弹性伸缩

Docker 体系结构

  • containerd 是一个守护进程,使用 runc 管理容器,向 Docker Engine 提供接口
  • shim 只负责管理一个容器
  • runc 是一个轻量级工具,只用来运行容器

Docker 内部组件

  • namespaces 命名空间,Linux 内核提供的一种对进程资源隔离的机制,例如进程、网络、挂载等资源
  • cgroups 控制组,Linux 内核提供的一种限制进程资源的机制,如 cpu、内存等资源
  • unonFS 联合文件系统,支持将不同位置的目录挂载到同一虚拟文件系统,形成一种分层的模型

Docker 架构

Docker 安装

  • 安装

    yum install -y yum-utils device-mapper-persistent-data lvm2
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    yum install docker-ce docker-ce-cli containerd.io
  • 阿里云加速

    sudo mkdir -p /etc/docker
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://6c3hbnlf.mirror.aliyuncs.com"]
    }
    EOF
    sudo systemctl daemon-reload
    sudo systemctl restart docker

image 镜像

  • Docker 将应用程序及其依赖,打包在 image 文件里。只有通过该文件,才能生成 Docker 容器
  • image 可以看做是容器的模板
  • Docker 工具 image 生成容器的实例,同一个 image 文件,可以生成多个同时运行的容器实例
  • 镜像不是一个单一的文件,而是有多层
  • 容器其实就是在镜像最上面加了一层读写层,在运行容器里做的任何文件改动,都会写到这个读写层里。如果容器删除了,最上面的读写层也就删除了,改动也就丢失了
  • 可以通过 docker history <ID/NAME> 查看镜像中各层内容及大小,每层对应着 Dockerfile 中的一条指令
命令 示例 语法
ls 查看全部镜像 docker image ls
search 查找镜像 docker search [imageName]
history 查看镜像历史 docker history [imageName]
inspect 显示一个或多个镜像详细信息 docker inspect [imageName]
pull 拉取镜像 docker pull [imageName]
push 推送一个镜像到镜像仓库 docker push [imageName]
rmi 删除镜像 docker rmi [imageName]
prune 移除未使用的镜像,没有标记或补任何容器引用 docker image prune
tag 标记本地镜像,将其归入某一仓库 docker tag [OPTIONS] IMAGE[:TAG] REGISTRYHOST/NAME[:TAG]
export 将容器文件系统作为一个 tar 归档文件导出到 stdout docker export [OPTIONS] CONTAINER
import 导入容器快照文件系统 tar 归档文件并创建镜像 docker import [OPTIONS] file/URL/-[REGISTRY[:TAG]]
save 将指定镜像保存成 tar docker save [OPTIONS] IMAGE [IMAGE...]
load 加载 tar 文件并创建镜像 docker load -i xx.tar
build 根据 Dockerfile 构建镜像 docker build [OPTIONS] PATH / URL / -
  • 用户既可以用 docker load 来导入镜像存储文件到本地镜像库,也可以使用 docker import 来导入一个容器快照到本地镜像库
  • 两者区别在于容器(import)快照文件将丢弃所有的历史记录和元数据信息(即仅保存当时的快照状态),而镜像(load)存储文件将保存完整记录,体积较大
  • 从容器(import)快照文件导入时可以重新指定标签等元数据信息
# 查看镜像
docker image ls

# 拉取镜像
docker pull hello-world

# 删除镜像
docker rmi hello-world

# 查看镜像历史
docker history hello-world

commit 制作个性化镜像

  • docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] 从容器创建一个新的镜像

    • -a 作者
    • -c 使用 Dockerfile 指令来创建镜像
    • -m 提交时的说明
    • -p 在 commit 时,将容器暂停
  • 停止容器后不会自动删除这个容器,除非在启动容器时指定了 --rm 标志
  • 使用 docker ps -a 命令查看 Docker 主机上包含停止的容器在内的所有容器
  • 停止状态的容器的可写层仍然占用磁盘空间,可以用 docker container prune 清理
  • 提交远程仓库

    docker login
    
    docker push

制作 Dockerfile

  • Docker 的镜像使用一层一层的文件组成
  • docker inspect 可以查看镜像或容器
  • Layers 就是镜像的层文件,只读不能修改,基于镜像创建的容器会共享这些文件层
docker inspect centos

编写 Dockerfile

  • -t --tag list 镜像名称
  • -f --file string 指定 Dockerfile 文件的位置
指令 含义 示例
FROM 构建的新镜像是基于哪个镜像 FROM centos:6
MAINTAINER 镜像作者 MAINTAINER cell
RUN 构建镜像时运行的 shell 命令 RUN yum install httpd
CMD CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换 CMD /usr/sbin/sshd -D
EXPOSE 声明容器运行的服务器端口 EXPOSE 80 443
ENV 设置容器内的环境变量 ENV MYSQL_ROOT_PASSWORD 12345
ADD 拷贝文件或目录到镜像中,如果是 URL 或者压缩包会自动下载和解压 ADD https://x.com/html.tar.gz /var/www.html
ADD html.tar.gz /var/www.html
COPY 拷贝文件或目录到镜像 COPY ./start.sh /start.sh
ENTRYPOINT 配置容器启动时运行的命令 ENTRYPOINT /bin/bash -c '/start.sh'
VOLUME 指定容器挂载点到宿主自动生成的目录或其他容器 VOLUME ["/var/lib/mysql"]
USER 为 RUN CMD 和 ENTRYPOINT 执行命令指定运行用户 USER cell
WORKDIR 为 RUN CMD ENTRYPOINT COPY ADD 设置工作目录 WORKDIR /data
HEALTHCHECK 健康检查 HEALTHCHECK --interval=5m --timeout=3s
ARG 在构建镜像时指定一些参数 ARG user
  • cmd 给出的是一个容器的默认的可执行体。即容器启动后,默认执行的命令。如果 docker run 没有指定任何执行命令或者 dockerfile 里也没有 entrypoint,那就会使用 cmd 指定的默认的执行命令执行。同时也从侧面说明了 entrypoint 的含义,它才是真正的容器启动以后要执行的命令。

dockerignore

排除,不打包到 image 中的文件路径

.git
node_modules

Dockerfile

  1. 安装 node
# 安装 nvm 
wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash # 下载命令
source /root/.bashrc # 加入系统变量
nvm install stable
node -v
npm i cnpm -g
npm i nrm -g
  1. 制作

下载基础镜像

docker pull node

创建项目

npm i express-gernerator

express myapp
cd myapp

npm i
npm run start

制作 Dockerfile

FROM node
COPY ./myapp /myapp
WORKDIR /myapp
RUN npm install # 构建镜像时运行的
EXPOSE 3000
CMD npm start # 启动容器时运行

制作忽略文件 .dockerignore

.git
node_modules

构建镜像

docker build -t myapp:1.0.0 .

查看镜像

docker image ls

启动容器

# -d 后台运行
# -p 3333 端口映射到容器 3000 端口
docker run -d -p 3333:3000 myapp:1.0.0

容器

  • docker run 可以从 image 生成一个正在运行的容器实例
  • docker container run 命令具有自动抓取 image 文件的功能,如果发现本地没有指定的 image,就会从仓库自动抓取
  • 有些容器会自动通知,有些不会自动停止
  • image 生成的容器实例,本身也是一个文件,称为容器文件
  • 容器生成,就会同时存在两个文件:image 和 容器文件
  • 关闭容器不会删除容器文件,只是容器停止运行
  • docker 容器的主线程(dockerfile 中 CMD 执行的命令)结束,容器会退出
命令 含义 示例
run 从镜像运行一个容器 docker run ubuntu /bin/echo 'hello world'
ls 列出容器 (-a 列出所有) docker container ls
inspect 显示一个或多个容器详细信息 docker inspect
attach 要 attach 上去的容器必须正在运行,可以同时连接上同一个 container 来共享屏幕 docker attach [OPTIONS] CONTAINER
stats 显示容器资源使用情况 docker container stats
top 显示一个容器运行的进程 docker container top
update 更新一个或多个容器配置 docker update -m 500m --memory-swap -16d1a25f95132
port 列出指定的容器的端口映射 docker run -d -p 8080:80 nginx
docker container port containerID
ps 查看当前运行的容器 docker container ps -a -l
kill [containerId] 终止容器(发送 SIGKILL) docker kill [containerId]
rm [containerId] 删除容器 docker container rm [containerId]
start [containerId] 启动已经生成、已经停止运行的容器文件 docker start [containerId]
stop [containerId] 终止容器运行(发送 SIGTERM) docker stop [containerId]
logs [containerId] 查看 docker 容器的输出 docker logs [containerId]
exec [containerId] 进入一个正在运行的 docker 容器执行命令 docker container exec -it xx /bin/bash
cp [containerId] 从正在运行的 Docker 容器里面,将文件拷贝到本机 docker container cp xx:/root/root.txt
commit [containerId] 根据一个现有容器创建一个新的镜像 docker commit -a "name" -m "myimg" xxx myimg:v1

数据盘 VOLUME

删除容器的时候,容器里面创建的文件也会被删除,如果有些数据想永久保存,如 web 服务器日志,数据库管理系统中的数据库,可以为容器创建一个数据盘

volume

  • volumes Docker 管理宿主机文件系统的一部分(/var/lib/docker/volumes)
  • 如果没有指定卷,会自动创建
  • 建议使用 --mount 更通用
  1. 创建数据卷
docker volume --help
docker volume create nginx-vol
docker volume ls
docker volume inspect nginx-vol

# 将 nginx-vol 数据卷挂载到 /usr/share/nginx/html,挂载后容器内的文件会同步到数据卷中
docker run -d --name=nginx1 --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
docker run -d --name=nginx2 -v nginx-vol:/usr/share/nginx/html -p 3000:80 nginx
  1. 删除数据卷
docker container stop nginx1 # 停止容器
docker container rm nginx1 # 删除容器
docker volume rm nginx-vol # 删除数据卷 
  1. 管理数据卷
docker volume ls # 列出所有数据盘
docker volume ls -f dangling=true # 列出已经孤立的数据盘
docker volume rm xx # 删除数据卷

Bind mounts

  • 该方式与 Linux 系统的 mount 方式很相似,即会覆盖容器内已存在的目录或文件,但不会改变容器内原有的文件,当 umount 后,容器内原有的文件就会还原
  • 创建容器的时候可以通过 -v--volume 给它指定数据卷
  • bind mounts 可以存储在宿主机系统的任意位置
  • 如果源文件 / 目录不存在,不会自动创建,会抛出错误
  • 如果挂载目标在容器中非空目录,则该目录现有内容将被隐藏

网络

安装 Docker 时,会自动创建三个网络,bridge (创建容器默认连接到此网络)、none、host。可以使用 --network 来指定容器应该连接到哪些网络

  • None:关闭容器网络功能,对外界完全隔离(--net none
  • host:不会虚拟出自己网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口 (--net host)
  • Bridge: 桥接网络,会为每一个容器分配 IP (默认,或 --net bridge)
docker inspect bridge # 查看网络信息

端口映射

# 查看镜像暴露的端口
docker image inspect nginx
# 让宿主机的 8080 映射到 docker 容器的 80
docker run -d --name port_nginx -p 8080:80 nginx
# 查看主机绑定的端口
docker container port port_nginx
# 指向主机的随机端口
docker run -d --name random_nginx --publish 80 nginx
docker run -d --name random_nginx --publish-all nginx
docker run -d --name random_nginx --P nginx

创建自定义网络

  • 可以创建多个网络,每个网络 IP 范围均不相同
  • docker 的自定义网络里面有一个 DNS 服务,可以通过容器名称服务主机
# 创建自定义网络
docker network create --driver bridge myweb 
# 查看自定义网络中的主机
docker network inspect myweb
# 创建容器时指定网络
docker run -d --name mynginx1 --net myweb nginx
docker run -d --name mynginx2 --net myweb nginx

# 连接到指定网络
docker run -d --name mynginx3 nginx
docker network connect myweb mynginx3
docker network disconnect myweb mynginx3

# 删除网络
docker network rm myweb

compose

  • Compose 通过一个配置文件来管理多个 Docker 容器
  • 在配置文件中,所有的容器都通过 services 来定义,然后使用 docker-compose 脚本来启动、停止和重启应用和应用中的服务以及所有依赖服务的容器
  • 步骤

    • 运行 docker-compose up,Conpose 将启动并运行这个应用程序配置文件组成
    • services 可以定义需要的服务,每个服务都有自己的名字、使用的镜像、挂载的数据卷、所属的网络和依赖的其他服务
    • volumes 定义数据卷,然后挂载到不同的服务上使用
  1. 安装 compose
yum -y install epel-release
yum -y install python-pip
yum clean all
pip install docker-compose

可能出现问题
官方教程

  1. 编写 docker-compose.yml
  • docker-compose.yml 中定义组成应用程序的服务,以便它们可以在隔离的环境中一起工作
  • 空格缩进表示层次
  • 冒号空格后面有空格
version: '2'
services: 
  nginx1:
    image: nginx
    ports:
      - "8080:80"
  nginx2:
    image: nginx
    ports:
      - "8081:80"
  1. 启动服务
docker-compose up # 执行当前目录下 docker-compose.yml
命令 服务
docker-compose up 启动所有服务
docker-compose up -d 后台启动所有服务
docker-compose ps 打印所有的容器
docker-compose stop 停止所有服务
docker-compose logs -f 实时跟踪日志
docker-compose exec nginx1 bash 进入 nginx1 服务系统
docker-compose rm nginx1 删除服务容器
docker-compose down 删除所有的网络和容器
  1. 配置数据卷
version: '3'
services: 
  nginx1:
    image: nginx
    ports:
      - "8080:80"
    networks:
      - "myweb"
    volumes:
      - "data:/data"
      - "/nginx1:/usr/share/nginx/html"
  nginx2:
    image: nginx
    ports:
      - "8081:80"
    networks:
      - "myweb"
    volumes:
      - "data:/data"
      - "/nginx2:/usr/share/nginx/html"
networks:
  myweb:
    driver: bridge
volumes:
  data:
    driver: local

node 项目

服务分类

  • db 使用 mariadb 作为数据库
  • node 启动 node 服务
  • web 使用 nginx 作为应用的 web 服务器

app 目录结构

文件 说明
docker-compose.yml 定义开发环境需要的服务
images/nginx/config/default.conf nginx 配置文件
images/node/Dockerfile node 的 Dockerfile 配置文件
images/node/web/package.json 项目文件
images/node/web/public/index.html 静态首页
images/node/web/server.js node 服务
|-- docker-compose.yml
|-- images
    |-- nginx
    |   |-- config
    |       |-- default.conf
    |-- node
        |-- Dockerfile
        |-- web
            |-- package.json
            |-- public
            |   |-- index.html
            |-- server.js
  • docker-compose.yml
version: "2"
services:
  node:
    build:
      context: "./images/node"
      dockerfile: Dockerfile
    depends_on:
      - db
  web:
    image: nginx
    ports:
      - "8080:80"
    volumes:
      - "./images/nginx/config:/etc/nginx/config.d"
      - "./images/node/web/public:/public"
    depends_on:
      - node
  db:
    image: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: "root"
      MYSQL_USER: "node"
      MYSQL_PASSWORD: "123456"
      MYSQL_DATABASE: "nodedb"
    volumes:
      - "db:/var/lib/mysql"
volumes:
  db:
    driver: local
  • Dockerfile
FROM node
COPY ./web /web
WORKDIR /web
EXPOSE 8080
RUN npm install
CMD npm start
  • nginx/config/default.config
server {
  listen 80;
  server_name localhost;
  root /public;
  index index.html index.htm;

  location /api {
    proxy_pass http://node:8080;
  }
}
  • server.js
const http = require('http');
http.createServer(function (req, res) {
  res.send('hello docker');
}).listen(8080);
  • package.json
{
  "scripts": {
    "start": "node server.js"
  }
}

实战应用

简单 Nginx 服务

# 拉取镜像
docker pull nginx

# 创建目录及页面
mkdir www
echo 'Hello Nginx' >> www/index.html

# 启动容器
docker run -p 8000:80 -v $PWD/www:/usr/share/nginx/html -d nginx 

# 查看
docker ps
# 停止
docker stop [containerId]
# 进入容器
docker exec -it [containerId] /bin/bash
# 退出容器
exit
# 删除容器 先停后删
docker stop [containerId]
docker rm [containerId]

定制镜像

  • 简单定制

    # 创建目录
    mkdir nginx
    cd nginx
    
    # 创建 Dockerfile
    vi Dockerfile
    
    # 定制镜像
    docker build -t nginx:cellinlab .
    # 查看镜像
    docker images
    
    # 启动容器
    docker run -p 80:80 -d nginx:cellinlab

    Dockerfile

    FROM nginx:latest
    RUN echo '<h1>Hello Nginx @ cellinlab</h1>' > /usr/share/nginx/html/index.html
  • 定制 Node.js

    # 创建目录
    mkdir node
    cd node
    
    # 初始化 npm 项目
    npm init -y
    npm i koa -S
    
    # 创建应用程序
    vi app.js
    
    # 定制镜像
    vi Dockerfile
    docker build -t mynode .
    
    # 启动容器
    docker run -p 3000:3000 -d mynode

    app.js

    const Koa = require('koa');
    const app = new Koa();
    app.use(ctx => {
      ctx.body = 'Hello Node width Docker';
    });
    app.listen(3000, () => {
      console.log('app started at 3000');
    });

    Dockerfile

    FROM node:10-alpine
    ADD . /app/
    WORKDIR /app
    RUN npm install
    EXPOSE 3000
    CMD ["node", "app.js"]
  • 定制 PM2

    # 拷贝上一个内容
    cp -R node pm2
    cd pm2
    
    # 新建 yml
    vi process.yml
    
    # 修改 Dockerfile
    vi Dockerfile
    
    # 构建和启动
    docker build -t mypm2 .
    docker run -p 3000:3000 -d mypm2

    process.yml

    apps:
      - script: app.js
        instances: 2
        watch: true
        env:
          NODE_ENV: production

    Dockerfile

    FROM keymetrics/pm2:latest-alpine
    WORKDIR /usr/src/app
    ADD . /usr/src/app
    RUN npm config set registry https://registry.npm.taobao.org/ && \
        npm i
    EXPOSE 3000
    CMD ["pm2-runtime", "start", "process.yml"]

Docker Compose

mongo-express 示例

# 创建项目
mkdir mongo
cd mongo

# 创建 yml
vi docker-compose.yml

# 运行 
docker-compose up

docker-compose.yml

version: '3.1'
services:
  mongo:
    image: mongo
    restart: always
    ports:
      - 27017:27017
  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8000:8081
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6月前
|
资源调度 前端开发 Shell
[docker] DevContainer高效开发(第二篇):前端开发体验
上面的配置只是最基本的配置,大部分情况我们是需要自定义配置,让容器更符合我们的需求。自定义配置就需要用到 Dockerfile,这个文件是 docker 的配置文件,可以在里面安装软件,配置环境等等。Dockerfile 的语法可以参考 官方文档。然后根据自己的需求编写 Dockerfile# 设置变量,由 .devcontainer.json 中的 args 传入# 指定 node 版本# 设置编码# 设置工作目录# 挂载 volume# 设置 bash 为默认 shell。
180 0
|
6月前
|
前端开发 jenkins 持续交付
新的centos7.9安装docker版本的jenkins2.436.1最新版本-前端项目发布(五)
新的centos7.9安装docker版本的jenkins2.436.1最新版本-前端项目发布(五)
173 1
|
6月前
|
前端开发 应用服务中间件 nginx
Nginx配置详解Docker部署Nginx使用Nginx部署vue前端项目
Nginx配置详解Docker部署Nginx使用Nginx部署vue前端项目
619 0
|
1月前
|
前端开发 开发工具 git
如何清理 docker 磁盘空间+修改 Gitea 服务器的 Webhook 设置+前端一些好学好用的代码规范-git hook+husky + commitlint
如何清理 docker 磁盘空间+修改 Gitea 服务器的 Webhook 设置+前端一些好学好用的代码规范-git hook+husky + commitlint
35 5
|
2月前
|
前端开发 应用服务中间件 nginx
docker部署本地前端项目思路
docker部署本地前端项目思路
41 7
|
1月前
|
JavaScript 前端开发 Docker
拿下奇怪的前端报错(二):nvm不可用报错`GLIBC_2.27‘‘GLIBCXX_3.4.20‘not Found?+ 使用docker构建多个前端项目实践
本文介绍了在多版本Node.js环境中使用nvm进行版本管理和遇到的问题,以及通过Docker化构建流程来解决兼容性问题的方法。文中详细描述了构建Docker镜像、启动临时容器复制构建产物的具体步骤,有效解决了不同项目对Node.js版本的不同需求。
|
4月前
|
前端开发 Docker 容器
前端 CSS 经典:mac docker 效果
前端 CSS 经典:mac docker 效果
51 0
|
6月前
|
前端开发 应用服务中间件 nginx
前端破圈使用Docker Nginx容器部署项目🏴‍☠️
前端破圈使用Docker Nginx容器部署项目🏴‍☠️
233 0
|
6月前
|
前端开发 Java 网络安全
解决docker中运行的jar包连不上前端程序
解决docker中运行的jar包连不上前端程序
|
6月前
|
前端开发 应用服务中间件 nginx
Docker 安装 Nginx 部署前端项目
Docker 安装 Nginx 部署前端项目
680 1
下一篇
无影云桌面