# Docker **Repository Path**: xiaoxinbupa/docker ## Basic Information - **Project Name**: Docker - **Description**: Docker 如果不浪,和k8s结合就没有其他容器技术的事情了 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2024-08-19 - **Last Updated**: 2025-03-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: 学习笔记, Docker ## README # Docker #### 介绍 Docker 如果不浪,和k8s结合就没有其他容器技术的事情了 ### docker容器技术 **容器的设计思想是为了隔离计算机中的各种资源** 最初的容器是以chroot为代表的文件隔离技术,但不能将主机名、网路、系统进程、用户等都不能隔离 Docker是一种以应用为核心,对程序文件、运行时环境、软件依赖包都可以封装打包、部署的技术手段 --Docker的容器中没有系统 DOcker三大概念: ​ 容器: 容器是一个运行在隔离环境中的程序 ---对象 ​ 镜像: 镜像是只读的模块,包含了创建容器所需的所有文件和配置信息 ---类 ​ 仓库:仓库是用来储存、分发、管理镜像的地方 ---存放管理类 ![image-20240803110459068](https://gitee.com/xiaoxinbupa/linux-note/raw/master/linux_base_picture/image-20240803110459068.png) **docker安装: 64操作系统、内核版本 > 2.6.32** 将对应的docker安装包拷贝到yum仓库 ```bash [root@ecs-proxy s4]# rsync -av docker/ /var/localrepo/docker/ [root@ecs-proxy s4]# createrepo --update /var/localrepo ``` 自行云购买主机 ![image-20240803114209829](https://gitee.com/xiaoxinbupa/linux-note/raw/master/linux_base_picture/image-20240803114209829.png) **dorker信息查询命令** | 命令 | 说明 | | --------------- | ------------------------ | | decker version | 查看服务器与客户端版本 | | docker info | 查看 docker 服务配置信息 | #### **容器安装部署** ​ 开启路由转发功能,保持容器和主机额的联系 ```bash [root@docker ~]# echo 'net.ipv4.ip_forward = 1' >>/etc/sysctl.conf [root@docker ~]# sysctl -p ``` ​ 安装软件包 ```bash [root@docker ~]# dnf install -y docker-ce [root@docker ~]# systemctl enable --now docker ``` 查看服务器与客户端版本 ```bash [root@docker ~]# docker version Client: Docker Engine - Community Version: 25.0.2 ... ... Server: Docker Engine - Community Engine: Version: 25.0.2 ``` **配置镜像仓库** ```bash [root@docker ~]# vim /etc/docker/daemon.json { "registry-mirrors": ["这里配置镜像仓库加速器地址"], "insecure-registries":[] } ``` ```bash [root@docker ~]# systemctl restart docker ``` 查看 docker 服务配置信息 ```bash [root@docker ~]# docker info ... ... Insecure Registries: 127.0.0.0/8 Registry Mirrors: https://镜像仓库加速器/ Live Restore Enabled: false ``` #### docker管理命令1 | 镜像管理命令 | 说明 | | ----------------------------------- | ------------------ | | docker images | 查看本机镜像 | | docker pull 镜像名称:标签 | 下载镜像 | | docker save 镜像名称:标签 -o 文件名 | 备份镜像为tar包 | | docker load -i 备份文件名称 | 导入备份的镜像文件 | | docker history 镜像名称:标签 | 查看镜像的制作历史 | ##### **pull、images、history** 下载 busybox:latest 镜像 ```bash ~]# docker pull busybox:latest ``` 查看本机镜像 ```bash ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest a9d583973f65 2 years ago 1.23MB ``` 查看镜像的制作历史 ```bash ~]# docker history busybox:latest IMAGE CREATED CREATED BY SIZE a9d583973f65 2 years ago /bin/sh -c #(nop) CMD ["sh"] 0B 2 years ago /bin/sh -c #(nop) ADD file:b4b40618f2… 1.23MB ``` ##### **save、load** 拷贝本阶段 public/myos.tar.xz 镜像包到 docker 主机(练习) ```bash [root@ecs-proxy s4]# rsync -av public/myos.tar.xz 192.168.1.31:./ ``` 导入镜像 ```bash ~]# docker load -i myos.tar.xz Loaded image: rockylinux:8.5 Loaded image: myos:8.5 Loaded image: myos:php-fpm Loaded image: myos:nginx Loaded image: myos:httpd Loaded image: myos:latest ``` 备份镜像为 tar 包 ```bash ~]# docker save busybox:latest -o busybox.tar ``` 查看本机镜像 ```bash ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myos php-fpm f70bdfd2042c 12 months ago 275MB myos nginx 10dc658da2fe 12 months ago 274MB myos latest 1de38c85c2d1 13 months ago 4.67MB myos httpd 9245e660f88f 13 months ago 299MB myos 8.5 621bfd7f9b46 13 months ago 249MB rockylinux 8.5 210996f98b85 2 years ago 205MB busybox latest a9d583973f65 2 years ago 1.23MB ``` #### docker管理命令2 | 容器管理命令 | 说明 | | ------------------------------------ | ------------------------------------------- | | docker run -it(d) 镜像名称:标签 | 创建容器 | | docker ps | 查看容器的信息 | | docker inspect 镜像名称\|容器名称 | 查询(容器/镜像)的详细信息 | | docker [start\|stop\|restart] 容器id | 启动、停止、重启容器 | | docker exec -it 容器ID 启动命令 | 在容器内执行命令 | | docker logs 容器ID | 查看容器日志 | | docker cp 路径1 路径2 | 拷贝文件:路径格式(本机路径、容器ID/路径) | ##### run 创建一个容器 ```bash ~]# docker run -it myos:8.5 [root@3aa1df05b795 /]# hostname 3aa1df05b795 ``` 创建后台容器 ```bash docker run -itd myos:httpd 6d6884244a995791f8171efa3ce81be1e9e51bedf25c3a5a67bac8bb7bc019b0 # 创建名为web1的后台容器 ``` 创建名为web1的后台容器 ```bash ~]# docker run -itd --name web1 myos:nginx 14b669a75a95e9ba590c37137abc9d828d2c769d46f69c35fb0e8cc98cc544c4 ``` ##### ps 查询容器状态--正在运行容器 ```bash ~]# docker ps CONTAINER ID IMAGE ... ... STATUS PORTS NAMES 14b669a75a95 myos:nginx ... ... Up 25 minutes 80/tcp web1 6d6884244a99 myos:httpd ... ... Up 25 minutes 80/tcp hawking ``` 查询容器状态--全部容器 ```bash ~]# docker ps -a CONTAINER ID IMAGE ... ... STATUS PORTS NAMES 14b669a75a95 myos:nginx ... ... Up 25 minutes 80/tcp web1 6d6884244a99 myos:httpd ... ... Up 25 minutes 80/tcp hawking 47ded92f442f myos:8.5 ... ... Exited (0) yonath ``` 查询容器状态--全部容器 ```bash ~]# docker ps -aq 14b669a75a95 6d6884244a99 47ded92f442f ``` ##### start、stop、restart ```bash ~]# docker ps -a CONTAINER ID IMAGE ... ... STATUS PORTS NAMES 14b669a75a95 myos:nginx ... ... Up 25 minutes 80/tcp web1 6d6884244a99 myos:httpd ... ... Up 25 minutes 80/tcp hawking 47ded92f442f myos:8.5 ... ... Exited (0) yonath ``` 启动容器 ```bash [root@docker ~]# docker start web1 47ded92f442f web1 47ded92f442f ``` ```bash ~]# docker ps -a CONTAINER ID IMAGE ... ... STATUS PORTS NAMES 14b669a75a95 myos:nginx ... ... Up 25 minutes 80/tcp web1 6d6884244a99 myos:httpd ... ... Up 25 minutes 80/tcp hawking 47ded92f442f myos:8.5 ... ... Up 2 seconds yonath ``` 停止容器 ```bash ~]# docker stop web1 web1 ``` 命令替换,停止所有容器 ```bash ~]# docker stop $(docker ps -aq) 14b669a75a95 6d6884244a99 47ded92f442f ``` ```bash ~]# docker ps -a CONTAINER ID IMAGE ... ... STATUS PORTS NAMES 14b669a75a95 myos:nginx ... ... Exited (0) web1 6d6884244a99 myos:httpd ... ... Exited (0) hawking 47ded92f442f myos:8.5 ... ... Exited (0) yonath ``` 重启容器 ```bash ~]# docker restart web1 web1 ``` ###### inspect 镜像名字/容器ID 查询镜像的详细信息 ```bash ~]# docker inspect myos:httpd { ...... "Cmd": [ "httpd", "-DFOREGROUND" ], ...... } ``` 查询容器的详细信息 ```bash ~]# docker inspect web1 6d6884244a99 [ { ... ... "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, ... ... "Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "", "IPPrefixLen": 0, ... ... } ]· ``` ###### exec、cp、logs exec在容器内执行非交互命令 ```bash ~]# docker exec -it web1 ls 50x.html index.html ``` exec......bash在容器内执行交互命令---故意改错nginx.conf的信息 ```bash [root@docker ~]# docker exec -it web1 bash [root@14b669a75a95 html]# ifconfig eth0 eth0: flags=4163 mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255 ... ... [root@14b669a75a95 html]# vim /usr/local/nginx/conf/nginx.conf 32: listen 80 [root@14b669a75a95 html]# exit ``` cp从容器内拷贝文件出来--关于容器一定是决定路径 ```bash [root@docker ~]# docker cp web1:/usr/local/nginx/conf ./ Successfully copied 45.6kB to /root/./ ``` 重启容器---会报错,容器起不来 ``` [root@docker ~]# docker restart web1 web1 [root@docker ~]# docker ps -a 14b669a75a95 myos:nginx ... ... Exited (1) web1 ``` log查看日志拍错 ```bash [root@docker ~]# docker logs web1 nginx: [emerg] invalid parameter "server_name" in /usr/local/nginx/conf/nginx.conf:33 ``` 修复配置文件错误 ---修改从容器拷贝过来的配置文件(自行拷贝) ```bash [root@docker ~]# vim conf/nginx.conf 32: listen 80; ``` ```bash [root@docker ~]# docker cp conf/nginx.conf web1:/usr/local/nginx/conf/nginx.conf Successfully copied 4.61kB to web1:/usr/local/nginx/conf/nginx.conf ``` ``` [root@docker ~]# docker restart web1 web1 [root@docker ~]# docker ps CONTAINER ID IMAGE ... ... STATUS PORTS NAMES 14b669a75a95 myos:nginx ... ... Up 2 seconds 80/tc ``` #### 简单镜像制作 ![image-20240803184404090](https://gitee.com/xiaoxinbupa/linux-note/raw/master/linux_base_picture/image-20240803184404090.png) 使用基础镜像创建一个容器 ```bash [root@docker ~]# docker run -itd --name linux rockylinux:8.5 ``` 删除容器内的Yum配置文件 ```bash [root@docker ~]# docker exec -it linux rm -rf /etc/yum.repos.d ``` 拷贝宿主机的Yum配置文件到容器内 ``` [root@docker ~]# docker cp /etc/yum.repos.d linux:/etc/ ``` 在容器内安装工具软件包 ```bash [root@docker ~]# docker exec -it linux dnf install -y net-tools vim-enhanced tree bash-completion iproute procps-ng psmisc ``` 清理缓存文件 ``` [root@docker ~]# docker exec -it linux dnf clean all ``` 停止容器 ``` [root@docker ~]# docker stop linux ``` 把容器制作成镜像 ```bash [root@docker ~]# docker commit linux mylinux:latest ``` 查看新制作的镜像 ```bash [root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mylinux latest b64da40467ae 3 seconds ago 249MB rockylinux 8.5 210996f98b85 13 months ago 205MB ``` 删除制作镜像的容器 ```bash [root@docker ~]# docker rm -f linux linux ``` ##### 容器部署应用 - 部署 apache 服务 ​ 删除所有容器 ```bash [root@docker ~]# docker rm -f $(docker ps -aq) ``` ​ 创建一个名为 myweb 的容器 ```bash [root@docker ~]# docker run -it --rm --name myweb mylinux:latest ``` ​ 在容器内安装部署 apache ```bash [root@a7f9d0c3e3e2 /]# dnf install -y httpd [root@a7f9d0c3e3e2 /]# echo "Hello World ." >/var/www/html/index.html [root@a7f9d0c3e3e2 /]# cat /usr/lib/systemd/system/httpd.service #设置环境变量 [root@a7f9d0c3e3e2 /]# export LANG=C #在前端启动httpd服务 [root@a7f9d0c3e3e2 /]# /usr/sbin/httpd -DFOREGROUND ``` 容器服务原理: ​ 上帝进程: 简单的说就是系统创建之初产生的第一个仅层 ​ 特点: ​ 没有父进程,PID==1, ​ 是所有程序的根进程 ​ 上帝进程的死亡系统实例也就关闭了 容器的上帝进程: ​ 容器的启动进程就是上帝进程 ​ 如果容器的启动进程关等同于容器关闭 ​ 上帝进程无法在后台执行 ​ 容器的启动进程必须放在前台执行 #### 镜像编排 ##### Dockerfile 详解 由于commit的局限性,Dockerfile可以设置默认的启动命令、设置环境变量、指定镜像开放某些特定的端口 | 指令 | 说明 | | ---------- | ------------------------------------------------------ | | FROM | 指定基础镜像(唯一) | | RUN | 在容器内执行命令,可以写多条 | | ADD | 把文件拷贝到容器内,如果文件是 tar.xx 格式,会自动解压 | | COPY | 把文件拷贝到容器内,不会自动解压 | | ENV | 设置启动容器的环境变量 | | WORKDIR | 设置启动容器的默认工作目录(唯一) | | CMD | 容器默认的启动参数(唯一) | | ENTRYPOINT | 容器默认的启动命令(唯一) | | USER | 启动容器使用的用户(唯一) | | EXPOSE | 使用镜像创建的容器默认监听使用的端口号/协议 | **编写 Dockerfile(案例1)** ```bash [root@docker ~]# mkdir myimg [root@docker ~]# vim myimg/Dockerfile FROM mylinux:latest CMD ["/bin/ls", "-l"] ``` **创建镜像(案例1)** ```bash [root@docker ~]# docker build -t img1:latest myimg ...... [root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE img1 latest 9278f72f8cb1 5 seconds ago 249MB mylinux latest e3b3d26bf0da 21 hours ago 249MB rockylinux 8.5 210996f98b85 13 months ago 205MB ``` **创建容器(案例1)** ```bash total 48 lrwxrwxrwx 1 root root 7 Oct 11 2021 bin -> usr/bin drwxr-xr-x 5 root root 360 Feb 5 04:21 dev drwxr-xr-x 1 root root 4096 Feb 5 04:21 etc drwxr-xr-x 2 root root 4096 Oct 11 2021 home ...... ``` **传递参数命令,覆盖 CMD 执行(案例1)** ```bash [root@docker ~]# docker run -it --rm img1:latest id uid=0(root) gid=0(root) groups=0(root) ``` ---- **(方案2)ENTRYPOINT 与 CMD 执行方式为:** **\${ENTRYPOINT} \${@-${CMD}} ** 注:\$@是调用所有位置i变量 、-values是设置初始值 ```bash [root@docker ~]# vim myimg/Dockerfile FROM mylinux:latest ENTRYPOINT ["echo"] CMD ["/bin/ls", "-l"] ``` **(方案2)创建镜像** ```bash [root@docker ~]# docker build -t img2:latest myimg ...... ``` **(方案2)CMD 做为参数传递,在容器内执行了 echo '/bin/ls -l'** ```bash [root@docker ~]# docker run -it --rm img2:latest /bin/ls -l ``` **(方案2)CMD 被替换,在容器内执行了 echo id** ```bash [root@docker ~]# docker run -it --rm img2:latest id id ``` **(方案3)制作测试文件** ```bash [root@docker ~]# tar -cf myimg/myfile.tar -C /etc hosts issue ``` **(方案3)编辑Dockerfile** ```bash [root@docker ~]# vim myimg/Dockerfile FROM mylinux:latest COPY myfile.tar /var/tmp/ ADD myfile.tar /tmp/ RUN id && touch /tmp/file1 USER nobody RUN id && touch /tmp/file2 ENV mymsg="Hello World" WORKDIR /tmp CMD ["/bin/bash"] ``` **(方案3)创建镜像** ```bash [root@docker ~]# docker build -t img3:latest myimg ...... ``` **(方案3)运行测试** ```bash [root@docker ~]# docker run -it --rm img3:latest ``` **(方案3)用 COPY 进来的文件还是 tar 包** ```bash bash-4.4$ tree /var/tmp /var/tmp `-- myfile.tar ``` **(方案3)使用 ADD 添加的文件已经被解压了** ```bash bash-4.4$ tree /tmp /tmp |-- hosts `-- issue ``` **(方案3)USER 指令设置使用 nobody 用户运行容器** ``` bash-4.4$ id uid=65534(nobody) gid=65534(nobody) groups=65534(nobody) ``` **(方案3)USER 指令前创建的文件是 root 权限,之后是 USER 用户权限** ```bash bash-4.4$ ls -l /tmp/file? -rw-r--r-- 1 root root 0 Feb 5 05:25 /tmp/file1 -rw-r--r-- 1 nobody nobody 0 Feb 5 05:25 /tmp/file2 ``` **(方案3)环境变量可以直接调用** ```bash bash-4.4$ echo ${mymsg} Hello World ``` **(方案3)WORKDIR 把工作目录设置到 /tmp** ```bash bash-4.4$ pwd /tmp ``` ##### Apache镜像制造 实验环境: 准备一个php页面文件 ```bash 拷贝 info.php 测试文件到 /root/ 目录下 [root@ecs-proxy s4]# rsync -av public/info.php 192.168.1.32:/root/ ``` **手工部署** 1. 创建容器 ```bash [root@docker ~]# docker run -it --name httpd mylinux:latest ``` 2. 安装软件包 ```bash [root@975fb53cb155 /]# dnf install -y httpd php && dnf clean all ``` 3. 修改配置文件 ```bash [root@975fb53cb155 /]# vim /etc/httpd/conf.modules.d/00-mpm.conf 11: LoadModule mpm_prefork_module ... ... # 去掉注释 23: # LoadModule mpm_event_module ... ... # 注释配置 [root@975fb53cb155 /]# export LANG=C [root@975fb53cb155 /]# /usr/sbin/httpd -DFOREGROUND # 使用快捷键 (ctrl-p, ctrl-q) 退出 ``` 4. 添加测试页面 ```bash [root@docker ~]# echo 'Welcome to The Apache.' >index.html [root@docker ~]# docker cp index.html httpd:/var/www/html/ [root@docker ~]# docker cp info.php httpd:/var/www/html/ ``` **制作镜像** 1. 编写 dockerfile 文件 ```bash etc/httpd/conf.modules.d/00-mpm.conf ENV LANG=C ADD myweb.tar.gz /var/www/html/ WORKDIR /var/www/html/ EXPOSE 80/tcp CMD ["/usr/sbin/httpd", "-DFOREGROUND"] [root@docker ~]# tar -czf httpd/myweb.tar.gz index.html info.php [root@docker ~]# docker build -t httpd:latest httpd ``` 2. 上转资源 ```bash [root@docker ~]# tar -czf httpd/myweb.tar.gz index.html info.php [root@docker ~]# docker build -t httpd:latest httpd ``` **验证测试** 1. 查看镜像并创建容器 ```bash [root@docker ~]# docker images httpd:latest REPOSITORY TAG IMAGE ID CREATED SIZE httpd latest c1e854cde1f4 About a minute ago 299MB [root@docker ~]# docker run -itd --name apache httpd:latest cc2b82ad0367172c344c7207def94c4c438027c60859e94883e440b53a860a93 ``` 2. 查看容器地址并访问验证 ```bash [root@docker ~]# docker inspect apache |grep -i IPAddress [root@docker ~]# curl http://172.17.0.2/info.php
   Array
   (
       [REMOTE_ADDR] => 172.17.0.1
       [REQUEST_METHOD] => GET
       [HTTP_USER_AGENT] => curl/7.61.1
       [REQUEST_URI] => /info.php
   )
   php_host:   2fbc8c132f7f
   1229
   [root@docker ~]# docker rm -f $(docker ps -aq)
   ```

##### **nginx 镜像制造**

实验准备:自行准备nginx的安装压缩包

```bash
拷贝 public/nginx-1.22.1.tar.gz 到 docker 主机
[root@ecs-proxy s4]# rsync -av public/nginx-1.22.1.tar.gz 192.168.1.32:/root/
```

**手工部署**

1. 创建容器

   ```bash
   [root@docker ~]# docker run -itd --name web mylinux:latest
   a1448547a12c15c8b1d1defa76e96f63f0f68ccb6bdeb59958ee57fc5dfac11e
   ```

2. 拷贝 nginx 源码包到容器内

   ```bash
   [root@docker ~]# docker cp nginx-1.22.1.tar.gz web:/
   Successfully copied 1.08MB to web:/
   ```

3. 进入容器配置

   ```bash
    [root@docker ~]# docker exec -it web bash
   ```

4. 安装编译工具和依赖软件包

   ```bash
   [root@a1448547a12c /]# dnf install -y openssl-devel pcre-devel gcc make
   [root@a1448547a12c /]# dnf clean all
   ```

5.  编译安装

    ```bash
    [root@a1448547a12c /]# tar zxf nginx-1.22.1.tar.gz 
    [root@a1448547a12c /]# cd nginx-1.22.1/
    [root@a1448547a12c nginx-1.22.1]# ./configure --prefix=/usr/local/nginx --with-pcre --with-http_ssl_module
    [root@a1448547a12c nginx-1.22.1]# make && make install
    ```

6. 设置默认首页

   ```bash
   root@a1448547a12c nginx-1.22.1]# echo 'Nginx is running !' >/usr/local/nginx/html/index.html
   ```

7. 添加 nginx 到环境变量

   ```bash
   root@a1448547a12c nginx-1.22.1]# echo 'Nginx is running !' >/usr/local/nginx/html/index.html
   ```

8. 启动服务(百度、ai)

   ```bash
   [root@a1448547a12c nginx-1.22.1]# nginx -g "daemon off;"
   ```

9. 退出容器

   ```bash
   [root@153c0df095e2 nginx-1.22.1]# exit
   ```

**制作镜像**

1. 将编译好的 nginx 拷贝出来(手工部署的容器)

   ```bash
   [root@docker ~]# mkdir nginx
   [root@docker ~]# docker cp web:/usr/local/nginx /root/nginx/nginx
   Successfully copied 5.82MB to /root/nginx/
   ```

2. 编写 Dockerfile 文件

   ```bash
   [root@docker ~]# vim nginx/Dockerfile 
   FROM mylinux:latest
   RUN  dnf install -y pcre openssl && dnf clean all
   COPY nginx /usr/local/nginx
   ENV  PATH=${PATH}:/usr/local/nginx/sbin
   WORKDIR /usr/local/nginx/html
   EXPOSE 80/tcp
   CMD  ["nginx", "-g", "daemon off;"]
   ```

3. 生成镜像

   ```bash
   [root@docker ~]# docker build -t nginx:latest nginx
   ......
   ```

**验证测试**

1. 查看镜像并创建容器

   ```bash
   [root@docker ~]# docker images nginx:latest
   REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
   nginx        latest    645dd2d9a8ec   3 minutes ago   274MB
   [root@docker ~]# docker run -itd --name nginx nginx:latest
   e440b53a860a93cc2b82ad0367172c344c7207def94c4c438027c60859e94883
   ```

2. 查看容器地址并访问验证

   ```bash
   [root@docker ~]# docker inspect nginx |grep -i IPAddress
   [root@docker ~]# curl http://172.17.0.2/
   Nginx is running !
   
   [root@docker ~]# docker rm -f $(docker ps -aq)
   ```

**多阶段镜像(扩展)**

1. 删除之前实验解压的nginx程序,只需要用到安装压缩包

```
[root@docker ~]# rm -rf nginx/nginx
[root@docker ~]# mv /root/nginx-1.22.1.tar.gz nginx/
```

​     2. 编写Dockerfile

```bash
[root@docker ~]# vim nginx/Dockerfile
# 第一阶段编译程序
FROM mylinux:latest as builder
ADD  nginx-1.22.1.tar.gz /
WORKDIR /nginx-1.22.1
RUN  dnf install -y openssl-devel pcre-devel gcc make
RUN  ./configure --prefix=/usr/local/nginx --with-pcre --with-http_ssl_module
RUN  make && make install
RUN  echo 'Nginx is running !' >/usr/local/nginx/html/index.html

# 第二阶段最终镜像
FROM mylinux:latest
RUN  dnf install -y pcre openssl && dnf clean all
COPY --from=builder /usr/local/nginx /usr/local/nginx
ENV  PATH=${PATH}:/usr/local/nginx/sbin
WORKDIR /usr/local/nginx/html
EXPOSE 80/tcp
CMD  ["nginx", "-g", "daemon off;"]

[root@docker ~]# docker build -t nginx:latest nginx
......
```

##### **php-fpm 镜像制造**

**手工部署**

1.  起容器,安装软件

    ```bash
    [root@docker ~]# docker run -it --name myphp mylinux:latest
    [root@cbcf3d90c02e /]# dnf install -y php-fpm
    ```

2. 修改配置文件

   ```bash
   [root@cbcf3d90c02e /]# vim /etc/php-fpm.d/www.conf
   38:  listen = 127.0.0.1:9000
   ```

3. 创建目录,并授权

   ```bash
   [root@cbcf3d90c02e /]# mkdir /run/php-fpm
   [root@cbcf3d90c02e /]# chown -R nobody.nobody /var/log/php-fpm /run/php-fpm
   ```

4. 使用 sudo 且换用户

   ```
   [root@cbcf3d90c02e /]# vim /etc/php-fpm.d/www.conf
   38:  listen = 127.0.0.1:9000
   ```

5. 使用 nobody 启动服务

   ```bash
   bash-4.4$ /usr/sbin/php-fpm --nodaemonize
   [04-Sep-2023 09:58:01] NOTICE: [pool www] 'user' directive is ignored when FPM is not running as root
   [04-Sep-2023 09:58:01] NOTICE: [pool www] 'group' directive is ignored when FPM is not running as root
   [04-Sep-2023 09:58:01] NOTICE: fpm is running, pid 1
   [04-Sep-2023 09:58:01] NOTICE: ready to handle connections
   [04-Sep-2023 09:58:01] NOTICE: systemd monitor interval set to 10000ms
   ```

##### docker 私有仓库

**主机清单:**

| 主机名   | ip地址       | 最低配置    |
| -------- | ------------ | ----------- |
| registry | 192.168.1.35 | 2CPU,4G内存 |

**registry 安装**

```bash
# 在 registry 上安装私有仓库
[root@registry ~]# dnf install -y docker-distribution
# 启动私有仓库,并设置开机自启动
[root@registry ~]# systemctl enable --now docker-distribution
```

**客户端配置**

- **所有 node 节点都需要配置**

```bash
[root@docker ~]# vim /etc/hosts
192.168.1.35    registry
# 修改配置文件
[root@docker ~]# vim /etc/docker/daemon.json
{
    "registry-mirrors": ["http://registry:5000"],
    "insecure-registries":["registry:5000"]
}
# 重启服务生效
[root@docker ~]# systemctl restart docker
[root@docker ~]# docker info
```

**上传镜像**

1. 给 nginx 镜像设置标签
2. 上传 nginx 镜像
3. 上传 php-fpm 镜像
4. 上传 httpd 镜像 

**验证测试**

```bash
查看镜像名称: curl http://仓库IP:5000/v2/_catalog
查看镜像标签: curl http://仓库IP:5000/v2/镜像路径/tags/list
使用易读格式: python3 -m json.tool
```

1. 查看仓库中所有镜像的名称

   ```bash
   [root@docker ~]# curl http://registry:5000/v2/_catalog
   {"repositories":["img/myimg", "library/httpd"]}
   ```

2. 查看某一镜像的所有标签

   ```bash
   [root@docker ~]# curl http://registry:5000/v2/img/myimg/tags/list
   {"name":"img/myimg","tags":["nginx", "php-fpm"]}
   ```

3. 易读格式查看镜像名称

   ```bash
   [root@docker ~]# curl http://registry:5000/v2/img/myimg/tags/list
           {"name":"img/myimg",
            "tags":["nginx", "php-fpm"]
            }
   ```

4. 易读格式查看镜像标签

   ```bash
   [root@docker ~]# curl -s http://registry:5000/v2/img/myimg/tags/list |python3 -m json.tool
   {
       "name": "img/myimg",
       "tags": [
           "nginx",
           "php-fpm"
       ]
   }
   ```

   **创建容器**

   1.  删除所有容器

      ```bash
      [root@docker ~]# docker rm -f $(docker ps -aq)
      ......
      ```

   2. 删除所有镜像

      ```bash
      [root@docker ~]# docker rmi -f $(docker images -q)
      ......
      ```

   3. 使用仓库中的镜像运行容器

      ```bash
      [root@docker ~]# docker run -itd --rm registry:5000/img/myimg:nginx
      2b7cd6d88a7665dbea0a4b3d99478e9f302c0a5661d7676d6d3bd3cb6d181
      ```

   4. library 是默认路径,可以省略路径地址

      ```bash
      [root@docker ~]# docker run -itd --rm httpd:latest
      634766f788d665dbea0a4b39709e0a2cc8624fd99478e9f302c0a5661d767
      ```

#### 对外发布服务

##### 端口绑定

- docker  run  -itd  -p 宿主机端口:容器端口  镜像:标签

1. 端口绑定

   ```bash
   [root@docker ~]# docker run -itd --rm --name web -p 80:80 myos:nginx
   ```

2. 绑定后,直接访问宿主机的 IP 地址即可

   ```bash
   [root@docker ~]# curl http://192.168.1.31
   Nginx is running !
   ```

3. 一个端口只能绑定唯一容器

   ```bash
   [root@docker ~]# docker run -itd --rm -p 80:80 myos:httpd
   ......
   Bind for 0.0.0.0:80 failed: port is already allocated.
   ```

4. 使用不同端口绑定

   ```bash
   [root@docker ~]# docker run -itd --rm -p 8080:80 myos:httpd
   3c22b1d9c7484c03648d9c64fe073953fb9460015b6f2a
   ```

5. 绑定后,访问验证

   ```bash
   [root@docker ~]# curl http://192.168.1.31:8080
   Welcome to The Apache.
   ```

##### 容器存储卷

- docker run -itd -v 宿主机对象:容器内对象 镜像:标签

**数据卷目录**

1. 创建卷目录,并添加测试页面

   ```bash
   [root@docker ~]# mkdir /var/webroot 
   [root@docker ~]# echo "hello world" >/var/webroot/index.html
   ```

2. 使用卷映射数据目录

   ```bash
   [root@docker ~]# docker rm -f web
   [root@docker ~]# docker run -itd --rm --name web -p 80:80 \
                      -v /var/webroot:/usr/local/nginx/html myos:nginx
   
   [root@docker ~]# curl http://192.168.1.31/
   hello worl
   ```

3. 修改数据卷内容可以直接在容器内体现

   ```bash
   [root@ecs-proxy s4]# rsync -av public/info.php 192.168.1.31:/var/webroot/
   [root@ecs-proxy s4]# curl http://192.168.1.31/info.php
   
      404 Not Found
      
      

404 Not Found


nginx/1.22.1
``` #### 容器网络通信 **实验架构图例** ![image-20240806101253752](https://gitee.com/xiaoxinbupa/linux-note/raw/master/linux_base_picture/image-20240806101253752.png)**共享名称空间** 1. 使用 nginx 的网络名称空间 ```bash root@docker ~]# docker run -itd --rm --name php --network=container:web myos:php-fpm d5a02b75486ce428f02b25f869f21299387fa4f51a605f478b466656d7c85c6f [root@docker ~]# curl http://192.168.1.31/info.php File not found. [root@docker ~]# docker exec -it web ss -ltun Netid State Recv-Q Send-Q Local Address:Port tcp LISTEN 0 128 127.0.0.1:9000 tcp LISTEN 0 128 *:80 ``` 2. 为 php 增加数据卷 ```bash [root@docker ~]# docker rm -f php [root@docker ~]# docker run -itd --rm --name php --network=container:web \ -v /var/webroot:/usr/local/nginx/html myos:php-fpm [root@docker ~]# curl http://192.168.1.31/info.php
   Array
   (
       [REMOTE_ADDR] => 192.168.1.31
       [REQUEST_METHOD] => GET
       [HTTP_USER_AGENT] => curl/7.61.1
       [REQUEST_URI] => /info.php
   )
   php_host:   da7df895c434
   1229
   ```

#### 微服务部署

**项目文件(自定义)**

注:不能使用tab键

```bash
[root@docker ~]# vim docker-compose.yaml
name: myweb
version: "3"
services:
  nginxsvc:
    container_name: nginx
    image: myos:nginx
```

##### **微服务治理命令**

- compose 子命令
  -  docker compose [-f xxx.yaml | -p project ] 子命令

| **指令**           | **说明**                   |
| ------------------ | -------------------------- |
| up                 | 创建项目并启动容器         |
| ls                 | 列出可以管理的项目         |
| images             | 列出项目使用的镜像         |
| ps                 | 显示项目中容器的状态       |
| logs               | 查看下项目中容器的日志     |
| start/stop/restart | 启动项目/停止项目/重启项目 |
| down               | 删除项目容器及网络         |

- **容器项目管理**

  - 创建项目,并启动

    docker compose  -f  xxx.yaml up  -d  

    ```bash
    [root@docker ~]# docker compose -f docker-compose.yaml up -d
    [+] Running 1/2
     ⠸ Network myweb_default  Created               0.4s 
     ✔ Container nginx        Started               0.3s 
    ```

  - 查看项目

    ​     docker compose ls -a/-all

    ```bash
    [root@docker ~]# docker compose ls -a
    NAME                STATUS              CONFIG FILES
    myweb               running(1)          /root/docker-compose.yaml
    ```

  - 查看项目中的容器状态

    docker compose -p  project  ps

    ```bash
    [root@docker ~]# docker compose -p myweb ps
    NAME      IMAGE        COMMAND                 SERVICE    PORTS
    nginx     myos:nginx   "nginx -g 'daemon…"     nginxsvc   80/tcp
    ```

  -  查看项目使用的镜像

     docker compose -p project  images

     ```bash
     [root@docker ~]# docker compose -p myweb images
     CONTAINER     REPOSITORY    TAG       IMAGE ID          SIZE
     nginx         myos          nginx     10dc658da2fe      274MB
     ```

  - 查看项目中容器的日志

    docker compose -p project logs

    ```bash
    [root@docker ~]# docker compose -p myweb logs
    nginx  | 2023/02/13 13:55:39 [error] 7#0: *1 open() ......
    
    ```

  - 启动、停止、重启项目

    docker compose -p project  start/stop/restart

    ```bash
    [root@docker ~]# docker compose -p myweb stop
    [+] Stopping 1/1
     ✔ Container nginx  Stopped                     0.1s 
    [root@docker ~]# docker compose -p myweb start
    [+] Running 1/1
     ✔ Container nginx  Started                     0.3s 
    [root@docker ~]# docker compose -p myweb restart
    [+] Restarting 1/1
     ✔ Container nginx  Started      
    ```

  - 删除项目

    docker compose -p project  down

    ```bash
    [root@docker ~]# docker compose -p myweb down
    [+] Running 2/1
     ✔ Container nginx        Removed               0.1s 
     ✔ Network myweb_default  Removed               0.1
    ```

##### **compose 语法**

| **指令**       | **说明**                                 |
| :------------- | ---------------------------------------- |
| networks       | 配置容器连接的网络                       |
| container_name | 指定容器名称                             |
| depends_on     | 解决容器的依赖、启动先后的问题           |
| command        | 覆盖容器启动后默认执行的命令             |
| environment    | 设置环境变量                             |
| image          | 指定为镜像名称或镜像 ID                  |
| network_mode   | 设置网络模式                             |
| restart        | 容器保护策略[always、no、on-failure]     |
| ports          | 暴露端口信息                             |
| volumes        | 数据卷,支持 [volume、bind、tmpfs、npipe] |

```

```

​		

- 验证项目

  - 创建,并启动项目

    ```bash
    [root@docker ~]# docker rm -f $(docker ps -aq)
    [root@docker ~]# docker compose -f docker-compose.yaml up -d
    [+] Running 2/2
     ⠿ Container nginx    Started             0.3s
     ⠿ Container php-fpm  Started             0.3s
    ```

  - 查看项目

    ```bash
    [root@docker ~]# docker compose ls -a
    NAME           STATUS        CONFIG FILES
    myweb          running(2)    /root/docker-compose.yaml
    ```

  - 查看容器状态,验证服务

    ```bash
    [root@docker ~]# docker compose -p myweb ps 
    NAME           COMMAND                    SERVICE    STATUS
    nginx          "nginx -g 'daemon of..."   nginx      running    ......
    php-fpm        "php-fpm --nodaemoni..."   php-fpm    running 
    ```

  - 访问 php 页面验证

    ```bash
    [root@docker ~]# curl -s http://127.0.0.1/info.php
    
    Array
    (
        [REMOTE_ADDR] => 172.17.0.1
        [REQUEST_METHOD] => GET
        [HTTP_USER_AGENT] => curl/7.61.1
        [REQUEST_URI] => /info.php
    )
    php_host:   7e037978c775
    1229
    ```


**嵌入式脚本**

```bash
[root@docker ~]# vim docker-script.yaml
name: mycmd
version: "3"
services:
  shell:
    container_name: mycmd
    image: myos:8.5
    command:
      - sh
      - -c
      - |
        for i in {1..9}
        do
            sleep 1
            echo "${HOSTNAME} && $${HOSTNAME}"
        done
```

```bash
[root@docker ~]# docker compose -f docker-script.yaml up -d
[root@docker ~]# docker compose ls -a
NAME                STATUS              CONFIG FILES
mycmd               running(1)          /root/docker-script.yaml
[root@docker ~]# docker compose -p mycmd logs
mycmd  | docker-0001 && af878f933612
mycmd  | docker-0001 && af878f933612
mycmd  | docker-0001 && af878f933612
......
```

##### harbor 仓库

| 主机名 | ip地址       | 最低配置    |
| ------ | ------------ | ----------- |
| harbor | 192.168.1.30 | 2CPU,4G内存 |

**安装部署 docker**

```bash
[root@harbor ~]# vim /etc/hosts
192.168.1.30    harbor

# 安装部署 docker 及 compose 组件
[root@harbor ~]# dnf install -y docker-ce
[root@harbor ~]# systemctl enable --now docker
```

- 拷贝软件包到 harbor 主机

```bash
[root@ecs-proxy s4]# rsync -av public/harbor-* 192.168.1.30:/root/
```

**创建 https 证书**

```bash
# 导入 harbor 项目镜像
[root@harbor ~]# tar -zxf harbor-v2.9.2.tgz -C /usr/local/
[root@harbor ~]# cd /usr/local/harbor
[root@harbor harbor]# docker load -i harbor.v2.9.2.tar.gz
# 创建 https 证书
[root@harbor harbor]# mkdir tls
[root@harbor harbor]# openssl genrsa -out tls/cert.key 2048
[root@harbor harbor]# openssl req -new -x509 -days 3650 \
                         -key tls/cert.key -out tls/cert.crt \
                         -subj "/C=CN/ST=BJ/L=BJ/O=Tedu/OU=NSD/CN=harbor"
```

**创建并启动项目**

```bash
# 修改配置文件
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
[root@harbor harbor]# vim harbor.yml
05:    hostname: harbor
08:    # http:
10:      # port: 80
17:    certificate: /usr/local/harbor/tls/cert.crt
18:    private_key: /usr/local/harbor/tls/cert.key
36:    harbor_admin_password: <登录密码>

# 预安装环境检查,生成项目文件
[root@harbor harbor]# /usr/local/harbor/prepare
# 创建并启动项目
[root@harbor harbor]# docker compose -f docker-compose.yml up -d
# 添加开机自启动
[root@harbor harbor]# chmod 0755 /etc/rc.d/rc.local
[root@harbor harbor]# echo "/usr/bin/docker compose -p harbor start" >>/etc/rc.d/rc.local
```

​           查看验证项目

```bash
# 查看项目
[root@harbor ~]# docker compose ls -a
NAME                STATUS              CONFIG FILES
harbor              running(9)          /usr/local/harbor/docker-compose.yml
# 查看容器状态
[root@harbor ~]# docker compose -p harbor ps
NAME                COMMAND                  SERVICE       STATUS
harbor-core         "/harbor/entrypoint.…"   core          running (healthy)
...
```

通过 ELB 发布 harbor 服务,通过浏览器配置管理

##### harbor 管理

| 容器管理命令  | 说明             |
| ------------- | ---------------- |
| docker login  | 登录私有镜像仓库 |
| docker logout | 退出登录         |

**登录私有仓库**

![image-20240806175440561](https://gitee.com/xiaoxinbupa/linux-note/raw/master/linux_base_picture/image-20240806175440561.png)

**创建普通用户**

![image-20240806175451041](https://gitee.com/xiaoxinbupa/linux-note/raw/master/linux_base_picture/image-20240806175451041.png)

**创建项目**

![image-20240806175611933](https://gitee.com/xiaoxinbupa/linux-note/raw/master/linux_base_picture/image-20240806175611933.png)



1. 添加主机配置

   ```bash
   [root@docker ~]# vim /etc/hosts
   192.168.1.30    harbor
   ```

2. 添加私有仓库配置

   ```
   [root@docker ~]# vim /etc/docker/daemon.json
   {
       "registry-mirrors": ["https://harbor:443", "其他镜像仓库"],
       "insecure-registries":["harbor:443", "其他镜像仓库"]
   }
   [root@docker ~]# systemctl restart docker
   ```

3. 登录 harbor 仓库

   ```bash
   [root@docker ~]# docker login harbor:443
   Username: <登录用户>
   Password: <登录密码>
   ... ...
   Login Succeeded
   ```

4. 认证信息记录文件

   ```bash
   [root@docker ~]# cat /root/.docker/config.json 
   {
       "auths": {
           "harbor:443": {
               "auth": "bHVjazoqKioqKioqKg=="
           }
       }
   }
   ```

5. 退出登录

   ```bash
   [root@docker ~]# docker logout harbor:443
   Removing login credentials for harbor:443
   ```

**上传镜像**

- 设置标签

  ```bash
  [root@docker ~]# docker tag myos:httpd harbor:443/private/httpd:latest
  ```

- 没有登录上传失败

  ```bash
  [root@docker ~]# docker push harbor:443/private/httpd:latest
  65dbea0a4b39: Preparing 
  unauthorized: unauthorized to access repository ......
  ```

- 登录成功后才可以上传

  ```bash
  [root@docker ~]# docker login harbor:443
  Username: <登录用户>
  Password: <登录密码>
  ```

- 上传成功

  ```bash
  [root@docker ~]# docker push harbor:443/private/httpd:latest
  The push refers to repository [harbor:443/private/httpd]
  ......
  ```

----

- 打标签,上传镜像到 library 项目(harbor没有权限)

  ```bash
  [root@docker ~]# docker tag myos:latest harbor:443/library/myos:latest
  ```

- 没有权限上传失败

  ```bash
  [root@docker ~]# docker push harbor:443/library/myos:latest
  The push refers to repository [harbor:443/library/myos]
  65dbea0a4b39: Preparing 
  unauthorized: unauthorized to access repository: 
  ......
  ```

- 赋权后重新上传镜像

  ![image-20240806174742093](https://gitee.com/xiaoxinbupa/linux-note/raw/master/linux_base_picture/image-20240806174742093.png)

  ```bash
  [root@docker ~]# docker push harbor:443/library/myos:latest
  The push refers to repository [harbor:443/library/myos]
  ......
  ```

###