# 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
```