Linux/Ubuntu入门之安装、使用Docker


Linux/Ubuntu入门之安装、使用Docker

docker的镜像总是几百M,大啊。。

前提条件

  1. 如果有旧版本,卸载旧版本 sudo apt-get remove docker docker-engine docker.io containerd runc
  2. Ubuntu版本大于16.04,LTS版本

核心概念

  • 镜像(images):docker镜像是用于创建docker容器的模板---一个特殊的文件系统
  • 容器(container):容器是独立运行的一个或一组应用---镜像运行时的实体
  • 客户端(client):客户端通过命令行或者其他工具使用dockerAPI与docker的守护进行通信
  • 宿主机(host):一个物理或虚拟机用于执行docker守护进程和容器
  • 仓库(Registry):docker仓库用来保存镜像---集中存放镜像文件的地方

安装步骤

基于apt-get,deb格式的文件 就更简单,sudo dpkg -i /path/package.deb

  1. 其他安装需要的包来允许apt通过HTTPS使用存储库 (新Ubuntu基本都有了,可略过)

     sudo apt-get install \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg \
        lsb-release
    
  2. 添加/信任Docker的官方GPG密钥

     curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    
  3. 设置存储库地址(稳定版 stable)

     echo \
      "deb [arch=amd64 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
    
  4. 完成上面几步才能使用apt包管理工具来安装Docker Engine (社区版)

    sudo apt-get update
    sudo apt-get install docker-ce docker-ce-cli containerd.io
    
  5. 运行hello world 镜像检验是否安装成功且能正常运行

     sudo docker run hello-world
    

    首次运行,没有这个镜像会从本地库中拉去然后输出Hello from Docker! .......

  6. 若要卸载Docker,删除软件包的同时还需要删除镜像容器和卷(就docker的相关文件)

     sudo apt-get purge docker-ce docker-ce-cli containerd.io
     
     sudo rm -rf /var/lib/docker
     sudo rm -rf /var/lib/containerd
    

是否使用root用户运行Docker?

docker官方是不建议用root,docker运维人员用root可能存在风险,做好权限隔离还是非常有必要。

那人如何使用非root账户管理呢?由于docker安装后会自动创建docker用户组,所以可以在docker用户组创建管理docker的用户或者把用户加入docker用户组,最后重启下

sudo useradd -g docker -d /home/appdocker  appdocker  
id appdocker # 查看该用户信息
#  用户id=1001(appdocker) 组id=998(docker) 组=998(docker)
sudo usermod -aG docker $USER  # 将用户加入docker组

没有权限的用户运行docker version docker ps会报错 权限拒绝,无法访问/var/run/docker.sock 这个文件

其他安装docker后续配置步骤参考官方文档:https://docs.docker.com/engine/install/linux-postinstall/

下文还是以root用户来操作...

修改仓库地址为国内镜像网站!

像npm需要设置仓库地址为淘宝的镜像网站一样,国内docker也需要将仓库改成默认的镜像网站

阿里云获取镜像地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

修改配置文件/etc/docker/daemon.json,没有就自己创建,修改后重启docker服务systemctl restart docker

{
  "registry-mirrors": ["https://xxxxxx"]
}
// 以下是直接可用的镜像地址
{
  "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn","http://hub-mirror.c.163.com","https://registry.docker-cn.com"]
}

Docker概念之Image、Dockerfile、Volume

镜像文件(Image)用于生成容器,即容器模板,Image存在继承关系,在每次继承可以添加个性化设置如添加软件。

  • Image是通用的。
  • Image存在应用程序及其依赖。
  • 常用Dockerfile来配置生成目标Image

构建脚本(Dockerfile)是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

  • FROM node:8.4:该 image 文件继承官方的 node image,冒号表示标签,这里标签是8.4,即8.4版本的 node。

  • COPY . /app:将当前目录下的所有文件(除了.dockerignore排除的路径),都拷贝进入 image 文件的/app目录。

  • WORKDIR /app:指定接下来的工作路径为/app

  • RUN npm install:在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入 image 文件。格式:RUN <命令行命令> | RUN ["可执行文件", "参数1", "参数2"]

  • EXPOSE 3000:将容器 3000 端口暴露出来, 允许外部连接这个端口。

    以上来自阮一峰的文章 和 https://www.runoob.com/docker/docker-dockerfile.html

数据卷(Volume)主要是用于数据持久化(也解决不同容器间数据共享问题),直接将数据写到宿主机上(我理解类似于目录映射),Volume由docker管理,位于/var/lib/docker/volumes目录,使用docker volume help 命令获取有关Volume的帮助。具体使用如下:

root@ubuntu:/# docker volume create todo-db
todo-db
root@ubuntu:/#  docker volume inspect todo-db
[
    {
        "CreatedAt": "2021-05-04T21:52:35+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": {},
        "Scope": "local"
    }
]

docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started为例,todo-db是一个卷的名字,-v todo-db:/etc/todos 中-v表示指定将卷(todo-db)mount到容器中的/etc/todos目录。如果指定卷不存在,docker会自动帮忙创建卷。

另一种方式数据持久化实现Use bind mounts: https://docs.docker.com/get-started/06_bind_mounts/

Docker概念之Netword

作用:让一台机子上独立的容器应用之间进行通信对话。

创建:

  1. 创建网络:docker network create app-net

  2. 为启动容器的命令添加额外参数来加入一个网络:--network app-net

  3. 为特定容器在Netword中的ip添加别名--network-alias mysql` (mysql将被解析为ip,类似于域名)

    ? 例:jdbc的url可以写成 url: jdbc:mysql://mysql:3306/db?

Dockerfile概念之CMD、RUN、ENV

RUN是在image文件的构建阶段执行,执行结果会被一起打包进去。每条RUN指令会在docker上新建一层,最好使用&& 连接命令

CMD是容器启动后要执行的命令,只能有一个CMD命令,docker container run后面的命令等同于CMD

ENV是设置容器的环境变量使用ENV key valueENV key1=value1 key2=value2两种格式

使用指南(Java&SpringBoot篇)

  1. 在某个工作目录下下载spring官方demo git clone https://github.com/spring-projects/spring-petclinic.git

  2. 进入spring-petclinic目录 输入 ./mvnw spring-boot:run 下载依赖项、构建项目并运行

  3. 然后访问 http://localhost:8080 确保可以正常运行

  4. 在这个目录下创建 Dockerfile文件

  5. 第一行是解析器指令(只能放第一行),用于告诉Docker builder 用什么语法来解析这个Dockerfile

    # syntax=docker/dockerfile:1
    
    FROM openjdk:16-alpine3.13
    # 创建工作目录,让后续命令更好写
    WORKDIR /app
    
    COPY .mvn/ .mvn
    COPY mvnw pom.xml ./
    # 根据pom文件来安装maven依赖项
    RUN ./mvnw dependency:go-offline
    
    COPY src ./src
    # 源码也准备好之后,启动项目
    CMD ["./mvnw", "spring-boot:run"]
    
  6. 创建.dockerignore文件用于排除不想被打包进镜像的文件和目录,java项目可以排除target文件夹

  7. 构建镜像 docker build --tag java-docker . 不显示的指定tag则为默认的latest

  8. 终端使用docker images命令查看构建的镜像

  9. --------------------朴实无华的分割线--------------------

  10. 用镜像启动容器使用命令docker run --publish 8080:8080 java-docker --publish简写是-p ,将容器的8080端口暴露到宿主机的8080端口

  11. 可在启动时添加 --detach或者-d 分离容器,使其后台自己运行

  12. 可在启动时添加 --rm参数,使在容器退出时自动清理容器并删除文件系统

spring官网指南 https://spring.io/guides/gs/spring-boot-docker/

手动部署方式:jar包配合dockerfile,基于基础镜像搞个新镜像(jar先上传到有docker的环境中,用于生成镜像)

Maven插件方式:使用插件 docker-maven-plugin

使用指南(Mysql篇)

  1. 为mysql的数据创建一个卷 docker volume create mysql

  2. 为mysql的配置创建一个卷 docker volume create mysql_config

  3. 为应用程序和数据库直接创建网桥网络 docker network create mysqlnet

  4. 运行一个MySQL容器,并附加到刚刚创建的卷和网络上(版本8.0.23,从docker hub下载)

    docker run -it --rm -d -v mysql_data:/var/lib/mysql \
    -v mysql_config:/etc/mysql/conf.d \
    --network mysqlnet \
    --name mysqlserver \
    -e MYSQL_USER=petclinic -e MYSQL_PASSWORD=petclinic \
    -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=petclinic \
    -p 3306:3306 mysql:8.0.23   
    
  5. 对于刚刚的SpringBoot篇,可以修改它的dockerfile来指定项目的profile切换到有关mysql的配置

    CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql"]
    
  6. 然后再重新构建镜像 docker build --tag java-docker .

  7. 同时多了mysql要连接,SpringBoot项目容器的也要有所修改

    docker run --rm -d \
    --name springboot-server \
    --network mysqlnet \
    -e MYSQL_URL=jdbc:mysql://mysqlserver/petclinic \
    -p 8080:8080 java-docker
    
  8. 不用分别启动两个容器,还能再偷懒!使用Compose进行本地开发!

    1. 在刚刚的springboot项目(petclinic)根目录下,创建docker-compose.dev.yml文件

      version: '3.8'
      services:
        petclinic:
          build:
            context: .
          ports:
            - 8000:8000
            - 8080:8080
          environment:
            - SERVER_PORT=8080
            - MYSQL_URL=jdbc:mysql://mysqlserver/petclinic
          volumes:
            - ./:/app
          command: ./mvnw spring-boot:run -Dspring-boot.run.profiles=mysql -Dspring-boot.run.jvmArguments="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000"
      
        mysqlserver:
          image: mysql:8.0.23
          ports:
            - 3306:3306
          environment:
            - MYSQL_ROOT_PASSWORD=
            - MYSQL_ALLOW_EMPTY_PASSWORD=true
            - MYSQL_USER=petclinic
            - MYSQL_PASSWORD=petclinic
            - MYSQL_DATABASE=petclinic
          volumes:
            - mysql_data:/var/lib/mysql
            - mysql_config:/etc/mysql/conf.d
      volumes:
        mysql_data:
        mysql_config:
      
    2. 相当于docker run的命令写到这个文件中了,同时mysqlserver也可以当作域名使用

    3. 执行compose.yml文件 docker-compose -f docker-compose.dev.yml up --build

    4. *连接调试器 https://docs.docker.com/language/java/develop/#connect-a-debugger

TODO 看到这了 https://docs.docker.com/language/java/run-tests/

参考链接

  1. Docker 入门教程(阮一峰) https://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html
  2. 官方使用案例教学 https://docs.docker.com/get-started/overview/
  3. 官方[run]参考 https://docs.docker.com/engine/reference/run/

相关