Linux进阶 | 万字详解Docker镜像的制作,手把手学会!
Posted chaochao️
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux进阶 | 万字详解Docker镜像的制作,手把手学会!相关的知识,希望对你有一定的参考价值。
创作不易,来了的客官点点关注,收藏,订阅一键三连❤😜
前言
运维之基础——Linux。我是一个即将毕业的大学生,超超。如果你也在学习Linux,不妨跟着萌新超超一起学习Linux,拿下Linux,一起加油,共同努力,拿到理想offer!
系列文章
Linux进阶 | Docker部署nginx的web服务,VOLUME的使用详解,实现数据持久化!
Linux进阶 | 2万字总结最详细的Docker的安装、底层隔离机制和简单使用!建议收藏,持续更新❤
Linux | 详解系统监控和常用命令(top free dstat)
Linux | 超超讲解SSH的原理与SSH的实现!建议收藏❤
概述
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。本期内容为Docker第三期,通过本期内容将会掌握docker的镜像制作。
目录
练习一:以python:3.9镜像为基础创建镜像,并以此启动容器并连接到redis
超超Docker学习思维导图
Docker思维导图将持续更新,欢迎大家订阅Linux栏目!
镜像的概念
Base镜像
Base 镜像有两层含义:
1. 不依赖其他镜像,从 scratch 构建。
2. 其他镜像可以之为基础进行扩展。
Base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等,以 CentOS 为例学习 base 镜像包含哪些内容。
[root@docker ~]# docker images centos
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 7 8652b9f0cb4c 9 months ago 204MB
使用docker pull centos下载最新版本的Centos镜像也就207M左右,而我们平时下载一个原生的centos镜像都是4G。
容器只能使用 Host 的 kernel,并且不能修改。所有容器都共用 host 的 kernel,在容器中没办法对 kernel 升级。如果容器对 kernel 版本有要求(比如应用只能在某个 kernel 版本下运行),则不建议用容器,这种场景虚拟机可能更合适。
Bootfs与rootfs
Bootfs:内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。
rootfs:容器内部的操作系统,用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。
镜像的分层结构
Docker 支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。
镜像的制作
制作前的疑问
镜像是什么?
答案:镜像由程序代码、基础操作系统、基础软件组成。
镜像是一个文件,里面包含了程序代码、基础操作系统、基础软件。
为什么要制作镜像,docker hub上不是有很多镜像吗?
答案:
1.不能满足我们的需要
2.不够安全,有安全隐患
谁去制作镜像?
答案: 一般都是开发人员去制作
也可以是运维人员去制作、权利非常大的工作人员。
镜像里有什么?
1.base 镜像 --》基础镜像--》提供操作系统,其他软件最基本的功能
基础镜像里的操作系统:Ubuntu、debian、centos等
Dockerfile
如果你想要从一个基础镜像开始建立一个自定义镜像,可以选择一步一步进行构建,也可以选择写一个配置文件,然后一条命令(docker build)完成构建,显然配置文件的方式可以更好地应对需求的变更,这个配置文件就是Dockerfile。
那DockerFile是什么?
Dockerfile: 用于描述镜像的生成规则(配置文件),Dockerfile中的每一条命令,都在Docker镜像中以一个独立镜像层的形式存在
DockerFile就类似与Linux的shell脚本,只不过DockerFile是用来构建镜像的
制作步骤
以制作nginx镜像为例启动web服务
1.新建一个空目录
[root@docker ~]# cd /mydocker/
[root@docker mydocker]# pwd
/mydocker
2.新建Dockerfile
[root@docker mydocker]# vim Dockerfile
[root@docker mydocker]# ls
Dockerfile
[root@docker mydocker]# cat Dockerfile
# Use an official Python runtime as a parent image 下载一个python2.7的镜像模板,已经有操作系统和安装好python2.7
FROM python:2.7-slim
# Set the working directory to /app #在docker容器里的工作目录-->进入docker容器的时候,所在的目录
WORKDIR /app
# Copy the current directory contents into the container at /app 复制当前目录下的所有的内容到容器里的/app目录下
ADD . /app
VOLUME ["/data_flask"]
# Install any needed packages specified in requirements.txt 制作镜像的时候运行
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable 设置环境变量,app.py运行时可以调用
ENV NAME World
# Run app.py when the container launches 容器启动时运行
CMD ["python", "app.py"]
3.新建requirements.txt文件
[root@docker mydocker]# vim requirements.txt
[root@docker mydocker]# ls
Dockerfile requirements.txt
[root@docker mydocker]# cat requirements.txt
Flask
Redis
4.新建app.py文件
[root@docker mydocker]# vim app.py
[root@docker mydocker]# ls
app.py Dockerfile requirements.txt
[root@docker mydocker]# cat app.py
from flask import Flask
from redis import Redis, RedisError
import os
import socket
# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
app = Flask(__name__)
@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"
html = "<h3>Hello {name}!</h3>" \\
"<b>Hostname:</b> {hostname}<br/>" \\
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
[root@docker mydocker]#
5.生成镜像,需要一点时间,因为下载安装很多东西
[root@docker mydocker]# docker build -t hellochao .
-t :指定要创建的目标镜像名
. :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径
注:此时可能会有错误爆出,是由于网络连接问题所导致。
解决方法:重启docker服务。
6.查看生成的镜像
[root@docker mydocker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hellochao latest b9cdb67a8db4 14 seconds ago 159MB
<none> <none> fbea61ffb278 32 minutes ago 148MB
ubuntu-chaochao 2.0 67596afe27b5 4 days ago 72.8MB
ubuntu latest 1318b700e415 3 weeks ago 72.8MB
redis latest aa4d65e670d6 3 weeks ago 105MB
nginx latest 08b152afcfae 3 weeks ago 133MB
mysql 5.7.35 8cf625070931 3 weeks ago 448MB
daocloud.io/nginx latest 6084105296a9 5 months ago 133MB
hello-world latest d1165f221234 5 months ago 13.3kB
centos 7 8652b9f0cb4c 9 months ago 204MB
python 2.7-slim eeb27ee6b893 16 months ago 148MB
centos/python-35-centos7 latest 2db34dda8fd8 2 years ago 645MB
7.以刚刚创建的镜像为基础创建容器
[root@docker mydocker]# docker run -d --name hello-chao-1 -p 8013:80 hellochao
b571dc07bf393737fe820cf5a7b6c5c61359b9979054d3484aeb1d573a788d71
[root@docker mydocker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b571dc07bf39 hellochao "python app.py" 2 minutes ago Up 2 minutes 0.0.0.0:8013->80/tcp, :::8013->80/tcp hello-chao-1
访问方式1:
用浏览器访问:网站-->宿主机IP+端口号
访问方式2:curl IP地址:端口号
Hello World!
Hostname: f4aeb5d5305a
Visits: cannot connect to Redis, counter disabled
因为redis数据库容器没有启动,flask web服务不能连接到redis数据库
8.启动redis容器
[root@docker mydocker]# docker run -d -p 6379:6379 --name hello-redis-1 redis
4ae649e2c9cf52e19e5cab4e4a6136d493390ff2e089838a4d65221e8e5b534a
9.再次启动一个自己制作镜像的容器,连接到redis容器
[root@docker mydocker]# docker run -d --name hello-chao-2 -p 8014:80 --link hello-redis-1:redis hellochao
1967d1eae722bd34e01f5bc575127e041a6caea15f48bd5f3f137ae1f2c744a9
10.访问web服务,效果如下:
方式一:用浏览器
方式二:curl
[root@docker ~]# curl 192.168.232.132:8014
<h3>Hello World!</h3><b>Hostname:</b> 1967d1eae722<br/><b>Visits:</b> 3[root@docker ~]#
Dockerfile里面的RUN和CMD是什么时候运行的?
RUN:构建镜像时候运行的,在临时启动的中间测试的容器里运行,会产生中间的镜像层
CMD:镜像制作好后,容器启动的时候运行
ADD和COPY
Dockerfile中的COPY指令和ADD指令都可以将主机上的资源复制或加入到容器镜像中,都是在构建镜像的过程中完成的。
COPY指令和ADD指令的唯一区别在于是否支持从远程URL获取资源。
COPY指令只能从执行docker build所在的主机上读取资源并复制到镜像中。
而ADD指令还支持通过URL从远程服务器读取资源并复制到镜像中。(推荐)
自己练习制作nginx镜像
1.部署环境
[root@docker ~]# mkdir/mydocker/nginx
2.创建Dockerfile
[root@docker nginx]# ls
Dockerfile install_nginx.sh nginx-1.21.1.tar.gz
[root@docker nginx]# vim Dockerfile
[root@docker nginx]# cat Dockerfile
FROM centos:7
ENV NGINX_VERSION 1.21.1
ENV AUTHOR ChaoChao
LABEL maintainer="lzc<2569138892@qq.com>"
RUN mkdir /nginx
WORKDIR /nginx
COPY . /nginx
RUN set -ex;\\
bash install_nginx.sh ; \\
yum install vim iputils net-tools iproute -y
EXPOSE 80
ENV PATH=/usr/local/nginx1/sbin:$PATH
STOPSIGNAL SIGQUIT
CMD ["nginx","-g","daemon off;"]
[root@docker nginx]#
3.构建nginx镜像
[root@docker nginx]#docker build -t chao-ngixn-1 .
[root@docker nginx]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
chao-nginx-1 latest f668613a9de5 6 seconds ago 543MB
getting-started-1 latest 78bc6143bbce 7 hours ago 383MB
getting-started latest 8224b1c2dc86 19 hours ago 374MB
hello-chao-3 latest a9c7a3290464 20 hours ago 923MB
hellochao latest b9cdb67a8db4 24 hours ago 159MB
<none> <none> fbea61ffb278 24 hours ago 148MB
python 3.9 4c7220cee541 31 hours ago 912MB
node 12-alpine dc1848067319 5 days ago 88.9MB
ubuntu-chaochao 2.0 67596afe27b5 5 days ago 72.8MB
ubuntu latest 1318b700e415 3 weeks ago 72.8MB
redis latest aa4d65e670d6 3 weeks ago 105MB
nginx latest 08b152afcfae 3 weeks ago 133MB
mysql 5.7.35 8cf625070931 3 weeks ago 448MB
daocloud.io/nginx latest 6084105296a9 5 months ago 133MB
hello-world latest d1165f221234 5 months ago 13.3kB
centos 7 8652b9f0cb4c 9 months ago 204MB
python 2.7-slim eeb27ee6b893 16 months ago 148MB
centos/python-35-centos7 latest 2db34dda8fd8 2 years ago 645MB
4.创建以新建镜像为基础的容器并测试是否实现功能
[root@docker nginx]# docker run -d --name chaochao-nginx-1 -p 8018:80 chao-nginx-1
fad41f8b6ee1da4034c8fd89a1a56c3588a28100850e7c5a9cfdb8f089eeef4f
[root@docker nginx]# curl 192.168.232.132:8018
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@docker nginx]# docker exec -it chaochao-nginx-1 /bin/bash
[root@fad41f8b6ee1 nginx]# ls
Dockerfile install_nginx.sh nginx-1.21.1 nginx-1.21.1.tar.gz
[root@fad41f8b6ee1 nginx]# vim chaochao.txt
[root@fad41f8b6ee1 nginx]# cat chaochao.txt
echo I am chaochao!
[root@fad41f8b6ee1 nginx]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
135: eth0@if136: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:0a brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.10/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@fad41f8b6ee1 nginx]# exit
exit
[root@docker nginx]# ls
Dockerfile install_nginx.sh nginx-1.21.1.tar.gz
5.更改index.html
方法一:利用挂载实现
[root@docker nginx]# docker run -dp 8019:80 -v /web:/usr/local/nginx1/html --name chaochao-nginx-2 chao-nginx-1
6e3f9a849ce179ad184e2c314651c86a4db8c3c7ab5f264f0af27baa6aa1a047
[root@docker nginx]#
方法二:使用卷
[root@docker nginx]# docker volume create chao-nginx-volume-1
chao-nginx-volume-1
[root@docker nginx]# docker volume inspect chao-nginx-volume-1
[
{
"CreatedAt": "2021-08-18T17:20:27+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/chao-nginx-volume-1/_data",
"Name": "chao-nginx-volume-1",
"Options": {},
"Scope": "local"
}
]
[root@docker nginx]# cd /var/lib/docker/volumes/chao-nginx-volume-1/_data
[root@docker _data]# cp /web/* .
[root@docker _data]# ls
1.jpg index.html rep.html
[root@docker _data]# docker run -dp 8020:80 --name chao-nginx-3 --mount source=chao-nginx-volume-1,target=/usr/local/nginx1/html/ chao-nginx-1
e0f8f8b0bfc40b8ad6d2e74a536b6e831dde444fbb8c536b37ead81e31c5d64c
练习
练习一:以python:3.9镜像为基础创建镜像,并以此启动容器并连接到redis
1.升级 hello-chao-1的镜像里的基础镜像为python:3.9,并将自己的镜像更名
2.启动容器和redis容器,测试访问
[root@docker ~]# cd mydocker2/
[root@docker mydocker2]# ls
[root@docker mydocker2]# cp /mydocker/* .
[root@docker mydocker2]# ls
app.py Dockerfile requirements.txt
[root@docker mydocker2]# vim Dockerfile
[root@docker mydocker2]# docker pull python:3.9
[root@docker mydocker2]# docker build -t hello-chao-3 .
[root@docker mydocker2]# curl 192.168.232.132:8015
<h3>Hello,I am Lizhichao!</h3><b>Hostname:</b> 232af106a331<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>[root@docker mydocker2]#
[root@docker mydocker2]# docker run -d --name hello-redis-2 -p 8011:6379 redis
181d9b51863a6ad888e7e53ac27070343396fab16c911851dfa2c4e7579b7f22
[root@docker mydocker2]# docker run -d --name hello-chao-5 -p 8016:80 --link hello-redis-2:redis hello-chao-3
080bdc9dcd9304597c27db1afd6e266fd6d8c37ae78fcf02bedf81809a085470
[root@docker mydocker2]# curl 192.168.232.132:8016
<h3>Hello,I am Lizhichao!</h3><b>Hostname:</b> 080bdc9dcd93<br/><b>Visits:</b> 1[root@docker mydocker2]# curl 192.168.232.132:8016
<h3>Hello,I am Lizhichao!</h3><b>Hostname:</b> 080bdc9dcd93<br/><b>Visits:</b> 2[root@docker mydocker2]#
练习二:实现docker官网的镜像制作
实现 https://docs.docker.com/get-started/02_our_app/ 官网的镜像制作
[root@docker ~]# ls
anaconda-ks.cfg getting-started-master.zip mydocker2 ubuntu-chao2.tar ubuntu-chao.tar
[root@docker ~]# unzip getting-started-master.zip
[root@docker ~]# ls
anaconda-ks.cfg getting-started-master getting-started-master.zip mydocker2 ubuntu-chao2.tar ubuntu-chao.tar
[root@docker ~]# cd getting-started-master
[root@docker getting-started-master]# ls
app docker-compose.yml docs LICENSE README.md yarn.lock
build.sh Dockerfile Jenkinsfile mkdocs.yml requirements.txt
[root@docker getting-started-master]# cd app
[root@docker app]#
[root@docker app]# ls
package.json spec src yarn.lock
[root@docker app]# vim Dockerfile
[root@docker app]# ls
Dockerfile package.json spec src yarn.lock
[root@docker app]# cat Dockerfile
#syntax=docker/dockerfile:1
FROM node:12-alpine
RUN apk add --no-cache python g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
[root@docker app]#
[root@docker app]# docker run -dp 3000:3000 getting-started-1
588fd20a79b9d8082507dc209e73fa8a51a1e6abb56bc019256afc0df43ac73a
[root@docker app]#
[root@docker app]# docker run -dp 3001:3000 --name chao-node-2 getting-started-1
b5c8d74e7be4426fb22e1c524e26bead8b160cd938ae6bebe2433a52c65ab33a
[root@docker app]#
创作不易,客官点个赞,评论一下吧!超超和你一起加油❤😜
以上是关于Linux进阶 | 万字详解Docker镜像的制作,手把手学会!的主要内容,如果未能解决你的问题,请参考以下文章