diff --git a/README.md b/README.md index 397aaea..00ec21d 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,5 @@ This repository is a playground for practising docker based programming following [docker-development-youtube-series](https://github.com/marcel-dempers/docker-development-youtube-series) * Topic 1: [Working with Dockerfiles (.NET, Golang, Python, NodeJS)](docs/working_with_dockerfiles.md) -* Topic 2: [Working with code (.NET, Golang, Python, NodeJS)] \ No newline at end of file +* Topic 2: [Working with code (.NET, Golang, Python, NodeJS)](docs/working_with_code.md) +* Topic 3: [Multistage & Layers](docs/multistage_layers.md) \ No newline at end of file diff --git a/c#/Dockerfile b/c#/Dockerfile index b0dbb22..b1bdaeb 100644 --- a/c#/Dockerfile +++ b/c#/Dockerfile @@ -1 +1,21 @@ -FROM mcr.microsoft.com/dotnet/core/sdk:2.2 \ No newline at end of file +############# DEV IMAGE ################# +FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch as dev + +RUN mkdir /app/ +WORKDIR /app/ + +COPY ./src/work.csproj /app/work.csproj +RUN dotnet restore + +COPY ./src/ /app/ +RUN mkdir /out/ +RUN dotnet publish --no-restore --output /out/ --configuration Release + +############## PRODUCT IMAGE ############# +FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch-slim as prod + +RUN mkdir /app/ +WORKDIR /app/ +COPY --from=dev /out/ /app/ +RUN chmod +x /app/ +CMD dotnet work.dll \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index eef3c82..4cebf45 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,7 +4,8 @@ services: container_name: csharp # image name image: cruxlight/csharp_sdk:1.0.0 build: - context: ./c# + context: ./c# + target: dev working_dir: /work entrypoint: /bin/sh stdin_open: true @@ -16,7 +17,9 @@ services: golang: container_name: golang image: cruxlight/golang_sdk:1.0.0 - build: ./golang + build: + context: ./golang + target: dev working_dir: /work entrypoint: /bin/sh stdin_open: true @@ -28,7 +31,9 @@ services: nodejs: container_name: nodejs image: cruxlight/nodejs:1.0.0 - build: ./nodejs + build: + context: ./nodejs + target: dev working_dir: /work entrypoint: /bin/sh stdin_open: true diff --git a/docs/multistage_layers.md b/docs/multistage_layers.md new file mode 100644 index 0000000..43ca631 --- /dev/null +++ b/docs/multistage_layers.md @@ -0,0 +1,88 @@ +# Multistage & Layers + +Previously, in [Topic 2, Working with Code](working_with_code.md), we have dockerfile to create isolated DEV environment, but we still have to manually `dotnet new/build/run` + +Target: Use multistage dockerfile to automatically setup DEV & PROD environment, where we only need to modify source code. + +## What is Docker Image Layering? + +dockerfile lay layers on top of another. So often changed layers should be in bottom to save image building time + +### General DEV + PROD multistage dockerfile structure + +```dockerfile +######## Dev stage ######### +# Start from a base image (Layer 1) +FROM base-SDK-image-here + +# install dependencies (Layer 2) +RUN pip install \npm install \go get + +# Copy source code into image (Layer 3) +COPY source + +# Run assembly to build app based on source code (Layer 4) +RUN build +``` + +Above is the dockerfile for a development environment. To product ready, we can use multistage. By giving above codes an alias, we can build multi-stage images + +continue dockerfile + +```dockerfile +####### Runtime stage ######### +# Using a runtime image instead of full SDK (Layer 5) +FROM another-image + +# Copy compiled app into runtime image to save space (Layer 6) +COPY output-from-stage-1 + +# Start app or entrypoint +RUN application +``` + +Benefit of this multistage, we can use debug tools in dev stage, but also keep product small in stage 2 + +## Modify dockerfile and docker-compose for multistage building + +### Add build target in docker-compose + +Adding build target in `build`, so docker-compose can be directly used to create DEV/PROD image. + +```docker-compose + build: + context: ./c# + target: dev +``` + +### Modify dockerfile + +```dockerfile +############# DEV IMAGE ################# +# Define a dev stage using `as` +FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch as dev + +# Defining a working directory +RUN mkdir /app/ +WORKDIR /app/ + +# ???? +COPY ./src/work.csproj /app/work.csproj +RUN dotnet restore + +# Copy the remaining source file +COPY ./src/ /app/ +RUN mkdir /out/ +RUN dotnet publish --no-restore --output /out/ --configuration Release + +############## PRODUCT IMAGE ############# +FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch-slim as prod + +RUN mkdir /app/ +WORKDIR /app/ + +# Copy binary into folder +COPY --from=dev /out/ /app/ +RUN chmod +x /app/ +CMD dotnet work.dll +``` \ No newline at end of file diff --git a/golang/Dockerfile b/golang/Dockerfile index 9bd917b..0e03708 100644 --- a/golang/Dockerfile +++ b/golang/Dockerfile @@ -1 +1,18 @@ -FROM golang:1.12.5-alpine3.9 as builder \ No newline at end of file +################ DEV IMAGE ################ +FROM golang:1.12.5-alpine3.9 as dev + +RUN apk update && apk upgrade && \ + apk add --no-cache git + +RUN go get github.com/sirupsen/logrus +RUN go get github.com/buaazp/fasthttprouter +RUN go get github.com/valyala/fasthttp + +WORKDIR /work +COPY ./src /work/ +RUN go build -o app + +################## PROD IMAGE ################# +FROM alpine:3.9 as prod +COPY --from=dev /work/app / +CMD ./app \ No newline at end of file diff --git a/nodejs/Dockerfile b/nodejs/Dockerfile index 56d9a22..f90ba3e 100644 --- a/nodejs/Dockerfile +++ b/nodejs/Dockerfile @@ -1 +1,16 @@ -FROM node:12.4.0-alpine \ No newline at end of file +########### DEV IMAGE ########## +FROM node:12.4.0-alpine as dev + +RUN mkdir /app/ +WORKDIR /app/ + +# package.json is the only one will be changed when new dependency added +COPY ./src/package.json /app/package.json +RUN npm install + +COPY ./src/ /app/ + +############ PROD IMAGE ############## +FROM dev as prod + +CMD node . \ No newline at end of file diff --git a/python/Dockerfile b/python/Dockerfile index caac651..7a285f7 100644 --- a/python/Dockerfile +++ b/python/Dockerfile @@ -1 +1,20 @@ -FROM python:3.7.3-alpine3.9 \ No newline at end of file +FROM python:3.7.3-alpine3.9 as dev + +RUN mkdir /app/ +WORKDIR /app/ + +COPY ./src/requirements.txt /app/requirements.txt +RUN pip install -r requirements.txt +COPY ./src/ /app/ + +############# PROD IMAGE ############## + +FROM python:3.7.3-alphine3.9 as prod + +RUN mkdir /app/ +WORKDIR /app/ + +COPY --from=dev /app/ /app/ +RUN pip install -r requirements.txt +ENV FLASK_APP=server.py +CMD flask run -h 0.0.0 -p 5000 \ No newline at end of file