Docker每日一阅(3):创建自定义镜像
文章目录
1 回顾
- 运行交互式的容器(
docker container run ... -i -t) - 后台运行容器(
docker container run ... -d) - 查看运行容器的日志(
docker container logs [container id]) - 关闭正在运行的容器(
docker container stop [container id])
2 任务描述
docker container commit [container id]创建镜像- Dockerfile创建镜像(
docker image build ...)
注:上述的指令基本都可以简写,比如,docker image build ...可以简写为docker build ...,但我不喜欢这么做,因为你写全了就很清楚其中的逻辑了,比如,我们使用docker build实际上是用dockerfile build了一个image。而docker container commit则是将一个container commit成为一个image。
3 通过commit语句创建镜像
首先,让我们把ubuntu:latest image(镜像)pull下来,在交互模式下运行:
docker container run -ti ubuntu bash
注意,如果我们不在ubuntu后面加冒号和版本号,系统就会默认pull下来最新版的镜像。terminal的结果如下:
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
7c3b88808835: Pull complete
Digest: sha256:8ae9bafbb64f63a50caab98fd3a5e37b3eb837a3e0780b78e5218e63193961f9
Status: Downloaded newer image for ubuntu:latest
root@f6732e34b067:/#
当我们再新建一个terminal,输入docker ps的时候,我们就能看见一个正在运行的container(容器)了:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6732e34b067 ubuntu "bash" About a minute ago Up About a minute crazy_germain
我们可以在进入镜像后,实行和Ubuntu系统一模一样的指令,比如(我们随便装几个东西):
apt-get update; \
apt-get install -y figlet; \
figlet "hello docker"
关于apt-get update,如果你觉得速度慢的话,可以在前面加两行(阿里的镜像源):
sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list; \
sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list
然后我们退出容器(exit),这个容器也就随之而停止运行了。
假设我们希望可以把这个容器(f6732e34b067)封装成一个我们自定义的镜像,在本地环境我们可以:
docker container commit f6732e34b067
f6732e34b067是container ID。这个时候,我们发现,本地系统多了一个镜像(docker image list):
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 118f27638e3f 4 seconds ago 108MB
ubuntu latest 2b4cba85892a 4 days ago 72.8MB
通过docker image tag 118f27638e3f ubuntu-cus,我们对新建的镜像重命名:
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu-cus latest 118f27638e3f 4 minutes ago 108MB
ubuntu latest 2b4cba85892a 4 days ago 72.8MB
在docker desktop里面,我们也能很明显地看到:

4 通过Dockerfile创建镜像
通过Dockerfile,我们通过一个文件提供了新建镜像的说明,这样管理更改变得更加容易,尤其是当镜像变得更大、更复杂时。这里我们列举一个简单的例子,先把代码跑通,把思路搞懂,然后我们在明天更加详细地进行解读。
我们在当前目录下创建一个main.py文件,里面就一行字:print("Hello my friend")。
然后,我们创建dockerfile,并且在里面写上:
FROM python:3.7-slim
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& apt-get clean \
&& apt-get update
COPY . /app
WORKDIR /app
CMD ["python","main.py"]
一共有五部分组成:
FROM:基础镜像RUN:相当于我们进入这个容器之后输入的命令COPY:我们将此目录下的文件复制到镜像指定的目录下(/app)WORKDIR:此处制定容器启动时使用的目录CMD:在容器启动是运行的命令
我们使用以下命令创建自定义的镜像:
docker image build -t python-cus:v1 .
-t指的是tag,注意,最后有一个.,不能漏掉,指的是读取此路径下的dockerfile。
等build完后,我们就能看到(docker image list)新建的镜像了(注意这个镜像的tag):
REPOSITORY TAG IMAGE ID CREATED SIZE
python-cus v1 5986f9b52932 18 seconds ago 138MB
然后,让我们来run一下这个镜像:
docker container run python-cus:v1
在terminal中会返回Hello my friend。
如果我们用交互式的方式进入这个容器:docker container run -it python-cus:v1 /bin/sh,我们输入ls和pwd,能看到,确实就像dockerfile所写的那样,所有的本地当前路径下的文件都被复制到了/app路径下,并且我们进入这个容器的位置就是/app:
# ls
README.md dockerfile img index.js main.py
# pwd
/app









