NET 6 and SQL Server development environment into a Docker container using Visual Studio Code’s Remote Development today. Although it went smoothly with the documentation, the problem arose after the project was versioned. I think the point of this article is that in today’s containerized, cross-platform era, line breaks actually have to be confronted, or else you’ll be at a loss for what to do.

Experience the feeling of developing in containers

  1. Install the Docker Desktop and Remote Development extensions first.

  2. Create the basic ASP.NET Core 6 project and open it with Visual Studio Code first.

    1
    2
    
    dotnet new web -n devcontainer-demo1
    code devcontainer-demo1
    
  3. Press F1 > Remote-Containers: Add Development Container Configuration Files

  4. Select a Dev Container template first: C# (.NET) and MS SQL

    C# (.NET) and MS SQL

  5. Select .NET version: 6.0-focal

    .NET version: 6.0-focal

  6. Select Node.js version: none

    Node.js version: none

  7. Select the tool to be used in the container: Here we do not select it first, we can just press OK to finish the setting

    press OK to finish the setting

    That’s all set! πŸ‘

  8. Next, let’s do Git version control.

    To do this, I’ll start by adding a .NET-specific .gitignore file.

    1
    
    dotnet new gitignore
    

    The following is the final version, basically each file you can click on to see.

    final version

    Establish version control.

    1
    2
    3
    
    git init
    git add .
    git commit -m "Initial commit"
    
  9. Run F1 > Remote-Containers: Reopen in Container to start automatically

    start automatically

    Behind this action, all the required container images are automatically created, and then automatically started, the container environment is automatically initialized (installing the necessary development tools), the necessary network connection port forwarding is turned on (Port Forwarding), and then you can smoothly develop, test, and execute in the Container container connected to Visual Studio Code.

Experience the problem after version control

Since the .devcontainer/Dockerfile file in the project is responsible for building all the environments in the Dev Container development container, it contains SQL-related tools such as sqlcmd, bcp, sqlpackage, etc.

The contents of this .devcontainer/Dockerfile are as follows

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
# [Choice] .NET version: 6.0-focal, 3.1-focal
ARG VARIANT="6.0-focal"
FROM mcr.microsoft.com/vscode/devcontainers/dotnet:0-${VARIANT}

# [Choice] Node.js version: none, lts/*, 18, 16, 14
ARG NODE_VERSION="none"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

# Install SQL Tools: SQLPackage and sqlcmd
COPY mssql/installSQLtools.sh installSQLtools.sh
RUN bash ./installSQLtools.sh \
     && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
#     && apt-get -y install --no-install-recommends <your-package-list-here>

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1

You can find that he has copied mssql/installSQLtools.sh to the container, the point is that the Dev Container provided by Microsoft is based on Ubuntu 20.04.4 LTS as the main operating system, and when running this command, it will require all Shell Scripts to be executed with LF as the main line break character, so the common Windows CRLF line break character is not available, and the process of building container image will be wrong!

Let’s take a look at the process of how this error occurred.

  1. The container does not contain the project source code.

    Microsoft’s Dev Container uses volumn mapping to mount source code into the container, so you only have the “project execution environment” in the container!

  2. Judging ~/.gitconfig settings

    When we first create a container image, it automatically copies the Windows local ~/.gitconfig domain-wide configuration file to the ~/.gitconfig container environment, so basically the Git settings under Ubuntu 20.04.4 LTS are exactly the same as Windows. But Windows has a default value of core.autocrlf=true, which means that when all files are checked out, all text files are automatically treated as line feeds with CRLF, but that’s a big problem!

  3. Retrieve the source code

    Since the .devcontainer/mssql/installSQLtools.sh file was initially saved as LF, it will be automatically converted to CRLF newlines as soon as the source code is retrieved, so we can expect the .devcontainer/Dockerfile to have Error!

    You can try removing the entire .devcontainer and retrieving the file with git reset --hard.

  4. Run F1 > Remote-Containers: Reopen Folder Locally to go back to Windows and open this project

    go back to Windows and open this project

  5. Run F1 > Rebuild Without Cache and Reopen in Container Rebuild the container image of the Dev Container

    Rebuild the container image of the Dev Container

At this point you will see the error message.

1
An error occurred setting up the container.

error message.

If you look at the Terminal, you can see the relatively detailed error message.

detailed error message

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
=>[internal] load build context
0.0s
=>=> transferring context: 787B
0.0s
=> CACHED[1/4]FROM mcr.microsoft.com/vscode/devcontainers/dotnet:0-6.0 0.0s=β†’>[2/4] RUN if ["none" !="none" ]; then su vscode -c "umask 0002 && . 0.55=β†’[3/4]COPY mssql/installSQLtools.sh installSQLtools.sh0.0s=> ERROR [4/4] RUN bash ./installsQLtools.sh && apt-get clean -y &&0.6s--- δΈ€
>[4/4] RUN bash ./installsQLtools.sh && apt-get clean -y && rm -rf /var/lib/apt/lists/*/tmp/library-scripts:
#0 0.583 Installing mssql-tools
#00.583 ./installSQLtools.sh: line 3: syntax error near unexpected token'$'\r'
#0 0.583 ./installSQLtools.sh: line 3: 'curl -sSL https://packages.microsoft.com'keys/microsoft.asc | (oUT=$(apt-key add - 2>&1) ll echo $ouT)
failed to solve: executor failed running [/bin/sh -c bash ./installSQLtools.sh&&apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts]: exit code: 2
[6681 ms] Error:Command failed: docker-compose --project-name devcontainer-demol_devcontainer

When the problem occurred, it wasn’t very understandable at first, but you should now know very well that it was the line break that caused the error!

The right solution

The most standard solution to this problem is as follows.

  1. Run F1 > Remote-Containers: Reopen Folder Locally to go back to Windows and open this project

  2. Create a .gitattributes file under the .devcontainer/mssql/ directory and add the following.

    1
    
    *.sh    text eol=lf
    

    This will ensure that all *.sh files in that directory will always use LF as a newline character when Git pulls them out.

  3. Delete the .devcontainer/mssql/*.sh file, and use git checkout or git reset --hard to retrieve the file.

    1
    2
    3
    4
    5
    
    # Be sure to delete the file first
    rm .devcontainer/mssql/*.sh
    
    # Execute the file retrieval operation after deletion
    git checkout -- .devcontainer/mssql/*.sh
    
  4. Run F1 > Rebuild Without Cache and Reopen in Container to rebuild the container image of Dev Container

You should be able to build the container again this time! πŸ‘

Conclusion

This problem is actually not likely to occur in macOS or Linux, only Windows users will encounter this situation, which makes me wonder if no Microsoft engineers are using Windows anymore ah? πŸ˜…

However, I still think that as long as you are a Windows-loving developer like me, you should understand the difference between CRLF and LF, so that you will step on fewer mines in the process of containerization in the future.