在学习Docker时候,就在想怎么去利用这个技术去做点什么。于是乎,我想既然可以把运行环境包装在容器里,那我就把平时的开发环境也放在容器里试试。
Dockerfile
创建一个dockerfile文件 输入以下内容
# 前端开发中,时常需要使用 shell 命令,而有一个较为完整的环境比较重要,因此选择了使用 ubuntu 作为基础,若在意容器大小的话,可自行选择适用的基础镜像
FROM debian
# 镜像作者信息
MAINTAINER Caster "919187569@qq.com"
# 设置环境变量
# 在Debian系列的操作系统中,内核支持多个安装参数,DEBIAN_FRONTEND就是其中之一,用以设置安装过程中的用户界面类型。
ENV DEBIAN_FRONTEND noninteractive
# 设置时区
ARG TZ=Asia/Shanghai
ENV TZ ${TZ}
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 用 root 用户操作
USER root
### 更换成中科大源和更新源
RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& apt-get clean \
&& apt-get update
# 安装相应工具
RUN apt-get install -y \
vim \
wget \
curl \
python \
git-core
SHELL ["/bin/bash", "--login", "-i", "-c"]
# 安装 nvm 和 node pnpm yarn vue和nest.js
ENV NVM_DIR /home/.nvm
ENV NODE_VERSION v16
RUN mkdir -p $NVM_DIR && \
curl -o- https://gitee.com/mirrors/nvm/raw/master/install.sh | bash \
&& . $NVM_DIR/nvm.sh \
&& nvm install ${NODE_VERSION} \
&& nvm use ${NODE_VERSION} \
&& nvm alias ${NODE_VERSION} \
&& ln -s `npm bin --global` /home/.node-bin \
&& npm install --global nrm \
&& nrm use taobao \
&& npm install -g pnpm \
&& pnpm config set registry http://registry.npm.taobao.org \
&& npm install --global yarn \
&& npm i -g @nestjs/cli \
&& npm i -g @vue/cli
# Add PATH for node
ENV PATH $PATH:/home/.node-bin
# 删除 apt/lists,可以减少最终镜像大小,详情见:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#general-guidelines-and-recommendations
# USER root
RUN rm -rf /var/lib/apt/lists/*
WORKDIR /var/wwwDocker Compose
上面虽然创建好了dockerfile,但是有时候开发环境镜像可能还不够,比如当我需要使用Mysql时候,最好是启动一个mysql镜像,更为方便。那么就可以配置一个docker compose文件,让docker帮我们启动一系列容器。
文件内容如下
version: '3'
services:
frontend:
build:
context: .
dockerfile: ./Dockerfile
tty: true
ports:
- 30000:3000
volumes:
- ./frontend/www:/var/www
networks:
- frontend
mysql:
image: mysql:5.7
ports:
- 33060:3306
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
environment:
- MYSQL_ROOT_PASSWORD=123456
networks:
- frontend
# 将容器置于同一 networks 即可直接通过容器名访问
networks:
frontend:
driver: bridge注意点
一开始我并没有加入
SHELL ["/bin/bash", "--login", "-i", "-c"]这导致了一个问题,就是我使用npm指令时候,哪怕安装了也是显示npm no found 我一直不理解,直到看到了stackoverflow的资料后才知道如何解决 就是加入上面这句放在dockerfile里,就能正确获取到npm指令了。
原因:
Dockerfile 中每一个指令都会建立一层layer,
RUN也不例外。每一个RUN的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit这一层的修改,构成新的镜像。
每个 RUN 语句都独立于其他语句运行,因此/bin/sh -c不会获得通常在登录 shell 中获取的任何环境变量。 也就是说,哪怕上面的RUN指令安装了nvm,下面的RUN指令也是获取不到的。 而RUN指令默认运行环境是/bin/sh
docker根据https://docs.docker.com/engine/reference/builder/#run的默认 [Linux] shell
RUN是/bin/sh -c
而我们可以用shell命令去修改运行环境
SHELL ["executable", "parameters"]SHELL 指令允许覆盖用于命令的 shell 形式的默认 shell。Linux 上的默认 shell 是 ["/bin/sh", "-c"],而在 Windows 上是 ["cmd", "/S", "/C"]。SHELL 指令必须以 JSON 形式写入 Dockerfile 中。
使用下面这句,就可以将变量环境统一为登录bash环境,也就能获取到正常使用的环境变量。
SHELL ["/bin/bash", "--login", "-i", "-c"]本文参考
https://juejin.cn/post/6991026939934801951
https://stackoverflow.com/questions/25899912/how-to-install-nvm-in-docker
https://stackoverflow.com/questions/20635472/using-the-run-instruction-in-a-dockerfile-with-source-does-not-work
