Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用
systemd
去启动后台服务,容器内没有后台服务的概念。
一些初学者将
CMD
写为:CMD service nginx start
然后发现容器执行后就立即退出了。甚至在容器内去使用
systemctl
命令结果却发现根本执行不了。这就是因为没有搞明白前台、后台的概念,没有区分容器和虚拟机的差异,依旧在以传统虚拟机的角度去理解容器。
正确的做法是直接执行
nginx
可执行文件,并且要求以前台形式运行。比如:CMD ["nginx", "-g", "daemon off;"]
2. EXPOSE
EXPOSE
指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P
时,会自动随机映射 EXPOSE
的端口。
要将
EXPOSE
和在运行时使用 -p <宿主端口>:<容器端口>
区分开来。-p
,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE
仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射3. WORKDIR
格式为
WORKDIR <工作目录路径>
。
使用
WORKDIR
指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR
会帮你建立目录。
之前提到一些初学者常犯的错误是把
Dockerfile
等同于 Shell 脚本来书写,这种错误的理解还可能会导致出现下面这样的错误:RUN cd /app
RUN echo "hello" > world.txt
如果将这个
Dockerfile
进行构建镜像运行后,会发现找不到 /app/world.txt
文件,或者其内容不是 hello
。原因其实很简单,在 Shell 中,连续两行是同一个进程执行环境,因此前一个命令修改的内存状态,会直接影响后一个命令;而在 Dockerfile
中,这两行 RUN
命令的执行环境根本不同,是两个完全不同的容器。这就是对 Dockerfile
构建分层存储的概念不了解所导致的错误。
之前说过每一个
RUN
都是启动一个容器、执行命令、然后提交存储层文件变更。第一层 RUN cd /app
的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。
因此如果需要改变以后各层的工作目录的位置,那么应该使用
WORKDIR
指令。
4. study
https://jeffreyfritz.com/2018/09/deploying-asp-net-core-with-net-framework-using-docker/
https://www.jinnsblog.com/2018/12/docker-dockerfile-guide.html
https://blog.alexellis.io/run-iis-asp-net-on-windows-10-with-docker/
http://www.codedata.com.tw/social-coding/docker-layman-abc/
https://columns.chicken-house.net/2018/05/12/msa-labs2-selfhost/
https://skychang.github.io/2015/07/30/%E8%AE%93-ASP-NET-MVC-%E5%9F%B7%E8%A1%8C%E6%96%BC-Docker/
沒有留言:
張貼留言