In this article we’ll use the Docker Plugin for Visual Studio Code. Docker allows us to package our applications into images and run them as containers on any platform that has Docker installed. We’ll use this plugin with two developer stacks: Node.js and Go.
You need to have docker installed on your work station. Instructions on how to install and run docker are available here, and it should be specific to the particular operation system you are running.
You also need to have Visual Studio Code installed.
Once you have Visual Studio Code installed, open it click on the extensions section on the left most pane, and search for Docker.
Once installed, you should notice a few new things in your Visual Studio Code instance. On the left most pane, there’s a new Docker section with the Docker logo, which when clicked opens the Docker Explorer with three sections. Images, Containers, Registries
There are also a few commands added to the command palette, which you can view by opening the command palette and typing in docker
.
We’ll use a Node.js application to demonstrate the capabilities the Docker plugin adds to VSCode.
Let’s create an Express server.
- mkdir docker-node
- cd docker-node
- npm init -y
- npm install --save express
- touch index.js
We should have a directory tree like this:
.
├── index.js
├── node_modules
├── package-lock.json
└── package.json
1 directory, 3 files
This is the content of index.js
const express = require('express')
const app = express()
app.listen(3000)
app.get('/', (req, res) => {
res.send('hello world')
})
Update package.json
to have a start script.
"scripts": {
"start": "node index.js"
},
Now, we can simply run this app with npm start
, and go to port 3000
and see the app working.
Traditionally, to add Docker, we would follow these steps.
docker build...
on the terminal to build the imagedocker run...
on the terminal to run the containerWith the plugin however, all we need to do is the following.
Open the command palette, and type in docker
, then select Docker: Add Docker files to Workspace
. It should be the first option. Press Enter
You will be asked to choose the platform/stack, select Node.js and press Enter
.
You will then be asked to choose a port. Write 3000
since it’s the port our app will listen to.
The following files are added to your workspace: .dockerignore
, docker-compose.debug.yml
, docker-compose.yml
, and Dockerfile
.
The .dockerignore
tells docker to ignore the files listed when adding files to the build image.
The docker-compose.debug.yml
will allow you to run docker-compose
with inspect, and attach a debugger.
version: '2.1'
services:
docker-node:
image: docker-node
build: .
environment:
NODE_ENV: development
ports:
- 3000:3000
- 9229:9229
command: node --inspect=0.0.0.0:9229 index.js
If you are debugging during development though, you may need to attach a volume so that changes you make on your local machine are persisted in the container.
The docker-compose.yml
file is a standard docker-compose file used to run docker-services. When you add other resources/services such as database connections and load balancers, you’ll edit this file.
version: '2.1'
services:
docker-node:
image: docker-node
build: .
environment:
NODE_ENV: production
ports:
- 3000:3000
The Dockerfile
, which is the most important here, since it has to be built, contains the instructions we would have to write manually if we did not have the plugin installed.
FROM node:8.9-alpine
ENV NODE_ENV production
WORKDIR /usr/src/app
COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"]
RUN npm install --production --silent && mv node_modules ../
COPY . .
EXPOSE 3000
CMD npm start
Next, to build the Image, open the VS Code command palette, and type in docker
then select Docker: Build Image
and press Enter
.
You’ll be prompted to select the Dockerfile, choose it and press Enter
.
Next you’ll be prompted to select the tag. Leave the default docker-node
selected and press Enter
.
The Integrated Terminal will open, and the build logs will show.
Finally, we need to run the container. Once again, open the command palette and type in docker run
, the select Docker: Run
A list of all containers in your system will show up, select docker-node:latest
, the one we tagged, and press Enter
.
The terminal will show the logs for the run command.
Notice it added the -p 3000:3000
exposing the port to our host machine so that we can run the application by visiting localhost:3000
.
We can also run the container by going to the left pane, selecting the Docker section, then under Images, choose the docker-node
image, right click and click on run.
The same logs will run on the terminal.
You’ll also notice that the images section above has a list of the images in your system. Once the docker-node container is running, We can check the running containers in the same section, and even stop them.
Above, Attach Shell
is selected, which is equivalent to the docker command below.
- docker exec -it <container> sh
This shows the below terminal log output.
You can see we’re in the container and we can list the files inside the container.
Stop the container, and try running the app with docker-compose. Open the command palette, find docker-compose and see the output.
If you are not familiar with Golang, you can skip to the next topic.
Docker is also built with Go
Let’s create a Go App.
- mkdir docker-go
- cd docker-go
- touch main.go
Your directory tree will have one file.
.
└── main.go
0 directories, 1 file
Here’s the content for the main.go
file.
package main
import (
"log"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World"))
}
func main() {
http.HandleFunc("/", helloHandler)
if err := http.ListenAndServe(":9000", nil); err != nil {
log.Fatalln("ListenAndServer Error", err)
}
}
You can run the App with:
- go run main.go
Let’s however use the VSCode Docker plugin to build an image and run the container.
Create the Dockerfile by opening the command palette, typing in Docker and selecting Docker: Add Dockerfile to Workspace
.
You will be prompted to select a platform, choose Go
and press Enter
.
You’ll then be prompted to select a port, write in port 9000
, since it’s the port we chose on our app, and press Enter
.
The following 4 files will be created. .dockerignore
, docker-compose.debug.yml
, docker-compose.yml
, and Dockerfile
.
The .dockerignore
file tells Docker to ignore some files when adding files to the image.
The docker-compose.debug.yml
and the docker-compose.yml
are used by Docker Compose to run the app. They are not that much different, since the debug file requires additional input, as debugging Go is more complex.
The Dockerfile
here is however the most interesting bit. The last two lines of the build stage
are commented out and added RUN go install -v ./...
# RUN go-wrapper download # "go get -d -v ./..."
# RUN go-wrapper install # "go install -v ./..."
RUN go install -v ./...
Here’s the final docker file.
#build stage
FROM golang:alpine AS builder
WORKDIR /go/src/app
COPY . .
RUN apk add --no-cache git
# RUN go-wrapper download # "go get -d -v ./..."
# RUN go-wrapper install # "go install -v ./..."
RUN go install -v ./...
#final stage
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY /go/bin/app /app
ENTRYPOINT ./app
LABEL Name=docker-go Version=0.0.1
EXPOSE 9000
This type of Dockerfile pattern is called multi-stage build, and it’s main advantage is optimization of Docker images. It’s mostly useful for compiled languages, which in most cases doesn’t require the compilation tools to run the compiled app. Go is a good example.
In a nutshell, we use part of the Docker build to compile the app, then copy the compiled binary to a lighter Docker image, and run it from there.
Next we need to build the image. Open the command palette, and type in docker-build
, select Docker: Build Image
and press Enter
.
You’ll be prompted to select the Dockerfile, leave the default selected and press Enter
.
Finally, you’ll be ask to pick an image tag. Leave the default docker-go:latest
and press Enter
.
You’ll see the build logs in the integrated terminal.
Lastly, we need to run the container. Open the command palette and type in docker run
. Select Docker: Run
and press Enter
.
You’ll be prompted to select the image. Select docker-go:latest
.
You’ll see the logs in the Integrated Terminal.
Like before, you can also run the container by selecting the Docker section in the left pane, and under containers, select docker-go
, right click on click Run.
You’ll then see the same docker run
logs.
Since our our running Docker container only had the binary, we can attach the shell, in the containers section.
We can the type in ls
in the attached shell in the Integrated Terminal, and we’ll see a binary file called app
, which corresponds to the Dockerfile.
We’ll finally look at other helpful features that come with the VSCode Docker plugin.
Docker inspect images: This allows you to inspect the images built and see the details in a JSON file.
Select the image you want and open the context menu, and select inspect image. A JSON file will be opened with the details.
Show container logs: This is also found in the context menu for running containers. We’ll use the running Node.js container The logs will be shown in the Integrated Terminal.
Registries: You can log in to your Docker registry and see the images you’ve built and pushed.
System Prune: This option allows you to run docker system prune
, which clears unused images your system. It’s available via the button with the windows and a cross in the Docker explorer.
Intellisense: If you have to write the Docker files (Dockerfile, docker-compose.yml) yourself, you’ll get useful intellisense when typing.
It will even give you available image tags. This is triggered by typing in the image name, then a full colon, and CMD
+ Space
.
Dockerfile Linting: When you have an error in your Dockerfiles, a squiggly line will appear in VS Code and when you hover over it, you’ll be shown what the error is.
The problems tab below VS Code will also show it.
The Docker plugin for VS Code can help you quickly set up and create your Dockerfiles, build them and run them, without typing many of the commands yourself.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!