目录
一、docker镜像说明
1.1 Docker镜像中有没有内核
1.2 为什么没有内核
1.3 容器中的程序后台运行会导致此容器启动后立即退出
1.4 Docker镜像的生命周期
1.5 制作镜像方式
二、 将现有容器通过docker commit手动构建镜像
2.1 基于容器手动制作镜像步骤
2.2 实战案例:基于busybox制作httpd镜像
2.3 实战案例:基于官方镜像生成的容器制作tomcat镜像
2.4 实战案例:基于CentOS的基础镜像利用yum安装手动制作nginx的镜像
2.5 实战案例:基于CentOS编译安装nginx镜像
一、docker镜像说明
1.1 Docker镜像中有没有内核
从镜像大小上面来说,一个比较小的镜像只有1MB多点或几MB,而内核文件需要几十MB, 因此镜像里面是没有内核的,镜像在被启动为容器后将直接使用宿主机的内核。而镜像本身则只提供相应的rootfs,即系统正常运行所必须的用户空间的文件系统,比如: /dev/,/proc,/bin,/etc等目录,容器当中/boot目录是空的,而/boot当中保存的就是与内核相关的文件和目录。
1.2 为什么没有内核
由于容器启动和运行过程中是直接使用了宿主机的内核,不会直接调用物理硬件,所以也不会涉及到硬件驱动,因此也无需容器内拥有自已的内核和驱动。而如果使用虚拟机技术,对应每个虚拟机都有自已独立的内核。
1.3 容器中的程序后台运行会导致此容器启动后立即退出
Docker容器如果希望启动后能持续运行,就必须有一个能前台持续运行的进程,如果在容器中启动传统的服务,如:httpd,nginx等均为后台进程模式运行,就导致 docker 在前台没有运行的应用,这样的容器启动后会立即退出。所以一般会将服务程序以前台方式运行,对于有一些可能不知道怎么实现前台运行的程序,只需要在你启动的该程序之后添加类似于 tail ,top 这种可以前台运行的程序即可. 比较常用的方法,如 tail -f /etc/hosts。
1.4 Docker镜像的生命周期
docker build .构建dockerfile生成镜像,当在容器中,定制安装了一些软件,想要实现某些效果,可以手动实现,docker commit 容器id。docker save导出镜像,docker load 导入镜像。stop,start,restart是关闭开启重启容器。一个最基础的镜像有些功能没有,需要自己装,如vim都没有,要自己装。yum是有的,就可以使用yum装vim。yum install -y vim。
1.5 制作镜像方式
Docker 镜像制作类似于虚拟机的镜像(模版)制作,即按照公司的实际业务需求将需要安装的软件、相关配置等基础环境配置完成,然后将其做成镜像,最后再批量从镜像批量生成容器实例,这样可以极大的简化相同环境的部署工作。
Docker的镜像制作分为手动制作(基于容器)和自动制作(基于DockerFile),企业通常都是基于Dockerfile制作镜像。
二、 将现有容器通过docker commit手动构建镜像
2.1 基于容器手动制作镜像步骤
制作镜像有手动commit和自动dockerfile。
手动制作格式:
docker commit 格式
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
# REPOSITORY 软件名
# TAG 版本号#选项 OPTIONS
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@ateam.com>")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)
#说明:
制作镜像和CONTAINER状态无关,停止状态也可以制作镜像
如果没有指定[REPOSITORY[:TAG]],REPOSITORY和TAG都为<none>
提交的时候标记TAG号: 生产当中常用,后期可以根据TAG标记创建不同版本的镜像以及创建不同版本的容器
基于容器手动制作镜像步骤具体如下:
1.拉取一个系统的官方基础镜像,如:centos或ubuntu
2.基于基础镜像启动一个容器,并进入到容器
3.在容器中做陪孩子操作
3.1 安装基础命令
3.2 配置运行环境
3.3 安装服务和配置服务
3.4 放业务程序代码
4.提交为一个新镜像docker commit
5.基于自己的镜像创建容器并测试访问。
2.2 实战案例:基于busybox制作httpd镜像
格式:
BusyBox v1.36.1 (2023-05-18 22:34:17 UTC) multi-call binary.
Usage: httpd [-ifv[v]] [-c CONFFILE] [-p [IP:]PORT] [-u USER[:GRP]] [-r REALM] [-h HOME]
or httpd -d/-e/-m STRINGListen for incoming HTTP requests
-i Inetd mode
-f Run in foreground #前台运行
-v[v] Verbose
-p [IP:]PORT Bind to IP:PORT (default *:80)
-u USER[:GRP] Set uid/gid after binding to port
-r REALM Authentication Realm for Basic Authentication
-h HOME Home directory (default .) #指定主站点, 否则是当前目录
-c FILE Configuration file (default {/etc,HOME}/httpd.conf)
-m STRING MD5 crypt STRING
-e STRING HTML encode STRING
-d STRING URL decode STRING
使用docker pull [镜像名] 拉取镜像到本地
初始镜像和容器:
启动busybox容器:
/ # mkdir /data/html -p #新建主站点目录
/ # echo "test page" > /data/html/index.html #新建站点目录
/ # httpd -f -h /data/html/ #-f前台启动 -h指定主站点
制作镜像:
查看制作的镜像:
启动制作好的容器:
访问到了我们写的主页面。
2.3 实战案例:基于官方镜像生成的容器制作tomcat镜像
先拉取镜像:docker pull images
查看镜像:docker images
下载启动tomcat容器:docker run -d -p 8080:8080 tomcat
进入容器,修改:docker exec -it [容器id] bash
复制页面文件:
打包成镜像:
启动镜像:
2.4 实战案例:基于CentOS的基础镜像利用yum安装手动制作nginx的镜像
启动容器:
修正时区 yum 源 :
在宿主机中下载Centos-8.repo:
[root@Node2 ~]#:wget http://mirrors.aliyun.com/repo/Centos-8.repo
--2024-08-01 16:41:50-- http://mirrors.aliyun.com/repo/Centos-8.repo
正在解析主机 mirrors.aliyun.com (mirrors.aliyun.com)... 58.221.32.237, 58.221.32.238, 58.221.32.239, ...
正在连接 mirrors.aliyun.com (mirrors.aliyun.com)|58.221.32.237|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:2590 (2.5K) [application/octet-stream]
正在保存至: “Centos-8.repo”
100%[===============================================================>] 2,590 --.-K/s 用时 0.006s
2024-08-01 16:41:50 (426 KB/s) - 已保存 “Centos-8.repo” [2590/2590])
查看相关容器的id,使用docker cp命令将Centos-8.repo文件拷贝进容器。
进入容器中,把根下的Centos-8.repo文件移动到yum.repos.d下。
移动之后,如果使用yum源,如果一个repo文件找不到,不会遍历该文件夹下的repo文件,所以创建一个文件夹bak,把原有的repo文件移动到bak中,只留下Centos-8.repo文件。
安装nginx,修改配置文件:
在全局设置中添加前台执行。
[root@6795422fabaf yum.repos.d]# vi /etc/nginx/nginx.conf
......
daemon off;
......
创建主页面:
echo "nginx test page in docker" > /usr/share/nginx/html/index.html
打包成镜像:
docker commit -a "auth" -m 'yum nginx' -c "EXPOSE 80 443" c1 centos:nginx-v1
启动容器:
docker run -d -p 80:80 --name n1 centos:nginx-v1 nginx
后面的nginx是命令,启动nginx服务。
2.5 实战案例:基于CentOS编译安装nginx镜像
在CentOS 基础镜像的容器之上手动编译安装nginx,然后再将此容器提交为镜像
编译安装分以下几步:13步
2.5.1 运行centos
由于是系统类镜像,加一个tail -f持续运行,容器就不会停止。
[root@Node2 ~]#:docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@Node2 ~]#:
[root@Node2 ~]#:docker run -d --name c1 centos:latest tail -f /etc/passwd
581180384bf7a52ee6983217d91b1d24c27f08243b015be230bb8d66634bf0fe
[root@Node2 ~]#:
[root@Node2 ~]#:docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
581180384bf7 centos:latest "tail -f /etc/passwd" 5 seconds ago Up 4 seconds c1
把本地的源复制到容器中的/下,yum下载源能够正常使用。
[root@Node2 ~]#:ll Centos-8.repo
-rw-r--r--. 1 root root 2590 8月 4 2022 Centos-8.repo
[root@Node2 ~]#:docker cp Centos-8.repo c1:/
Successfully copied 4.61kB to c1:/
2.5.2 安装依赖包
依赖包要先修改源。才能使用yum。
[root@Node2 ~]#:docker exec -it c1 bash
[root@581180384bf7 /]# ls
Centos-8.repo dev home lib64 media opt root sbin sys usr
bin etc lib lost+found mnt proc run srv tmp var
[root@581180384bf7 /]# mkdir /etc/yum.repos.d/bak
[root@581180384bf7 /]# mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak
[root@581180384bf7 /]# mv Centos-8.repo /etc/yum.repos.d/
下载依赖包,包括vim,wget
[root@581180384bf7 /]# yum -y install gcc gcc-c++ make automake pcre pcre-devel zlib zlib-devel openssl openssl-devel wget vim net-tools
......
vim-common-2:8.0.1763-16.el8.x86_64
vim-enhanced-2:8.0.1763-16.el8.x86_64
vim-filesystem-2:8.0.1763-16.el8.noarch
wget-1.19.5-10.el8.x86_64
which-2.21-16.el8.x86_64
zlib-devel-1.2.11-17.el8.x86_64
Complete!
2.5.3 修改时区
时区是配置文件/etc/localtime起作用。
2.5.4 创建一个用户
[root@581180384bf7 /]# useradd -r -s /sbin/nologin nginx
2.5.5 下载nginx包
wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@581180384bf7 /]# wget http://nginx.org/download/nginx-1.18.0.tar.gz
......
nginx-1.18.0.tar.gz 100%[=====================================>] 1015K 997KB/s in 1.0s
2024-08-01 18:22:55 (997 KB/s) - ‘nginx-1.18.0.tar.gz’ saved [1039530/1039530]
2.5.6 解压编译安装到指定目录
[root@581180384bf7 /]# ls
bin etc lib lost+found mnt opt root sbin sys usr
dev home lib64 media nginx-1.18.0.tar.gz proc run srv tmp var
[root@581180384bf7 /]# tar xf nginx-1.18.0.tar.gz
[root@581180384bf7 /]# cd nginx-1.18.0
[root@581180384bf7 nginx-1.18.0]# ./configure --prefix=/apps/nginx
......
编译安装:
[root@581180384bf7 nginx-1.18.0]# make && make install
......
test -d '/apps/nginx/logs' \
|| mkdir -p '/apps/nginx/logs'
make[1]: Leaving directory '/nginx-1.18.0'
2.5.7 修改为前台启动
[root@581180384bf7 nginx-1.18.0]# vim /apps/nginx/conf/nginx.conf
......
daemon off;
......
2.5.8 绝对路径,检查语法
[root@581180384bf7 nginx-1.18.0]# /apps/nginx/sbin/nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
2.5.9 获取IP地址
[root@581180384bf7 nginx-1.18.0]# hostname -I
172.17.0.2
2.5.10 绝对路径启动服务
[root@581180384bf7 nginx-1.18.0]# ss -natp | grep 80
[root@581180384bf7 nginx-1.18.0]#
[root@581180384bf7 nginx-1.18.0]# /apps/nginx/sbin/nginx
再开一个终端:进入容器,绝对路径启动后,查看80端口:
可以看到容器内部访问nginx服务成功。
打包成镜像:
[root@Node2 ~]#:docker commit -m "nginx1.8.0" -c "CMD /apps/nginx/sbin/nginx" 581180384bf7 nginx1.18.0-centos8:v1
sha256:5f0b53d14c2a10d693e3e35247a531bbdc6da2aa5e5e455875428119d677ae63
[root@Node2 ~]#:
[root@Node2 ~]#:docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx1.18.0-centos8 v1 5f0b53d14c2a 7 seconds ago 583MB
centos nginx-v1 04ea6a202135 About an hour ago 343MB
tomcat 10.0.14 726200e5bb17 3 hours ago 684MB
httpd-b 1.0 760a661b0b57 3 hours ago 1.24MB
httpd-busybox v1.0 5329ca751e9c 4 hours ago 1.24MB
busybox latest beae173ccac6 2 years ago 1.24MB
nginx latest 605c77e624dd 2 years ago 141MB
tomcat latest fb5657adc892 2 years ago 680MB
mysql 5.7.29 3218b38490ce 2 years ago 516MB
httpd latest dabbfbe0c57b 2 years ago 144MB
alpine latest c059bfaa849c 2 years ago 5.59MB
centos latest 5d0da3dc9764 2 years ago 231MB
此时,镜像中就成了我们基于centos编译安装的nginx镜像。
测试:启动容器:
由于该容器里面运行着nginx。运行容器时我们指定了端口映射,90:80。我们可以测试访问一下本地的90端口。是否成功。
发现是可以访问运行的这个镜像的。
---end---