Skip to content
This repository was archived by the owner on Nov 30, 2023. It is now read-only.

Commit d64dc90

Browse files
authored
Adding Postgres Support to Go Dev Container (#1239)
1 parent 2e31d04 commit d64dc90

File tree

11 files changed

+516
-0
lines changed

11 files changed

+516
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
POSTGRES_USER=postgres
2+
POSTGRES_PASSWORD=postgres
3+
POSTGRES_DB=postgres
4+
POSTGRES_HOSTNAME=localhost
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# [Choice] Go version (use -bullseye variants on local arm64/Apple Silicon): 1, 1.16, 1.17, 1-bullseye, 1.16-bullseye, 1.17-bullseye, 1-buster, 1.16-buster, 1.17-buster
2+
ARG VARIANT=1-bullseye
3+
FROM mcr.microsoft.com/vscode/devcontainers/go:0-${VARIANT}
4+
5+
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
6+
ARG NODE_VERSION="none"
7+
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
8+
9+
# [Optional] Uncomment this section to install additional OS packages.
10+
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
11+
# && apt-get -y install --no-install-recommends <your-package-list-here>
12+
13+
# [Optional] Add more packages to the below lines to use go get to install anything else you need
14+
USER vscode
15+
RUN go get -x github.com/lib/pq
16+
USER root
17+
18+
# [Optional] Uncomment this line to install global node packages.
19+
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "Go & PostgreSQL",
3+
"dockerComposeFile": "docker-compose.yml",
4+
"service": "app",
5+
"workspaceFolder": "/workspace",
6+
7+
// Set *default* container specific settings.json values on container create.
8+
"settings": {
9+
"go.toolsManagement.checkForUpdates": "local",
10+
"go.useLanguageServer": true,
11+
"go.gopath": "/go",
12+
"go.goroot": "/usr/local/go",
13+
},
14+
15+
// Add the IDs of extensions you want installed when the container is created.
16+
"extensions": [
17+
"golang.Go"
18+
],
19+
20+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
21+
// "forwardPorts": [5432],
22+
23+
// Use 'postCreateCommand' to run commands after the container is created.
24+
// "postCreateCommand": "go version",
25+
26+
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
27+
"remoteUser": "vscode"
28+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
version: '3.8'
2+
3+
volumes:
4+
postgres-data:
5+
6+
services:
7+
app:
8+
build:
9+
context: .
10+
dockerfile: Dockerfile
11+
args:
12+
# [Choice] Go version 1, 1.16, 1.17
13+
# Append -bullseye or -buster to pin to an OS version.
14+
# Use -bullseye variants on local arm64/Apple Silicon.
15+
VARIANT: 1-bullseye
16+
# Options
17+
NODE_VERSION: "lts/*"
18+
env_file:
19+
# Ensure that the variables in .env match the same variables in devcontainer.json
20+
- .env
21+
22+
# Security Opt and cap_add allow for C++ based debuggers to work.
23+
# See `runArgs`: https://github.com/Microsoft/vscode-docs/blob/main/docs/remote/devcontainerjson-reference.md
24+
# security_opt:
25+
# - seccomp:unconfined
26+
# cap_add:
27+
# - SYS_PTRACE
28+
29+
volumes:
30+
- ..:/workspace:cached
31+
32+
# Overrides default command so things don't shut down after the process ends.
33+
command: sleep infinity
34+
35+
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
36+
network_mode: service:db
37+
38+
# Uncomment the next line to use a non-root user for all processes.
39+
# user: vscode
40+
41+
# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
42+
# (Adding the "ports" property to this file will not forward from a Codespace.)
43+
44+
db:
45+
image: postgres:latest
46+
restart: unless-stopped
47+
volumes:
48+
- postgres-data:/var/lib/postgresql/data
49+
env_file:
50+
# Ensure that the variables in .env match the same variables in devcontainer.json
51+
- .env
52+
53+
54+
# Add "forwardPorts": ["5432"] to **devcontainer.json** to forward PostgreSQL locally.
55+
# (Adding the "ports" property to this file will not forward from a Codespace.)

containers/go-postgres/.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work

containers/go-postgres/.npmignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
README.md
2+
test-project
3+
history
4+
definition-manifest.json
5+
.devcontainer/library-scripts
6+
.vscode
7+
.npmignore
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "Launch",
6+
"type": "go",
7+
"request": "launch",
8+
"mode": "debug",
9+
"program": "${workspaceFolder}/test-project/hello.go"
10+
}
11+
]
12+
}

containers/go-postgres/README.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Go
2+
3+
## Summary
4+
5+
*Use and develop Go + Postgres applications. Includes appropriate runtime args, Go, common tools, extensions, and dependencies.*
6+
7+
| Metadata | Value |
8+
|----------|-------|
9+
| *Contributors* | The VS Code Team |
10+
| *Categories* | Core, Languages |
11+
| *Definition type* | Docker Compose |
12+
| *Available image variants* | [See GO definition](../go) |
13+
| *Supported architecture(s)* | x86-64, arm64/aarch64 for `bullseye` variants |
14+
| *Works in Codespaces* | Yes |
15+
| *Container host OS support* | Linux, macOS, Windows |
16+
| *Container OS* | Debian |
17+
| *Languages, platforms* | Go |
18+
19+
## Table of Contents
20+
21+
- [Go](#go)
22+
- [Summary](#summary)
23+
- [Using this definition](#using-this-definition)
24+
- [Installing Node.js](#installing-nodejs)
25+
- [Adding the definition to a project or codespace](#adding-the-definition-to-a-project-or-codespace)
26+
- [Using the PostgreSQL Database](#using-the-postgresql-database)
27+
- [Adding another service](#adding-another-service)
28+
- [Installing GO Dependencies](#installing-go-dependencies)
29+
- [Testing the definition](#testing-the-definition)
30+
- [Debugging Security](#debugging-security)
31+
- [License](#license)
32+
33+
## Using this definition
34+
This definition creates two containers, one for Go and one for PostgreSQL. VS Code will attach to the Go container, and from within that container the PostgreSQL container will be available on **`localhost`** port 5432. The `.env` file sets the default credentials for the Postgres Database. The database is named `postgres` with a user of `postgres` whose password is `postgres`, and if desired this may be changed in `.env`. Data is stored in a volume named `postgres-data`.
35+
36+
While the definition itself works unmodified, you can select the version of Go the container uses by updating the `VARIANT` arg in the included `.devcontainer/docker-compose.yml` (and rebuilding if you've already created the container).
37+
38+
```yaml
39+
build:
40+
context: .
41+
dockerfile: Dockerfile
42+
args:
43+
# [Choice] Go version 1, 1.16, 1.17
44+
# Append -bullseye or -buster to pin to an OS version.
45+
# Use -bullseye variants on local arm64/Apple Silicon.
46+
VARIANT: 1.17
47+
```
48+
49+
### Installing Node.js
50+
51+
Given JavaScript front-end web client code written for use in conjunction with a Go back-end often requires the use of Node.js-based utilities to build, this container also includes `nvm` so that you can easily install Node.js. You can change the version of Node.js installed or disable its installation by updating the `args` property in `.devcontainer/docker-compose.yml`.
52+
53+
```yaml
54+
args:
55+
VARIANT: 1
56+
# Options
57+
NODE_VERSION: "14" # Set to "none" to skip Node.js installation
58+
```
59+
60+
### Adding the definition to a project or codespace
61+
62+
1. If this is your first time using a development container, please see getting started information on [setting up](https://aka.ms/vscode-remote/containers/getting-started) Remote-Containers or [creating a codespace](https://aka.ms/ghcs-open-codespace) using GitHub Codespaces.
63+
64+
2. Start VS Code and open your project folder or connect to a codespace.
65+
66+
3. Press <kbd>F1</kbd> select and **Add Development Container Configuration Files...** command for **Remote-Containers** or **Codespaces**.
67+
68+
> **Note:** If needed, you can drag-and-drop the `.devcontainer` folder from this sub-folder in a locally cloned copy of this repository into the VS Code file explorer instead of using the command.
69+
70+
4. Select this definition. You may also need to select **Show All Definitions...** for it to appear.
71+
72+
5. Finally, press <kbd>F1</kbd> and run **Remote-Containers: Reopen Folder in Container** or **Codespaces: Rebuild Container** to start using the definition.
73+
74+
## Using the PostgreSQL Database
75+
You can connect to PostgreSQL from an external tool when using VS Code by updating `.devcontainer/devcontainer.json` as follows:
76+
77+
```json
78+
"forwardPorts": [ "5432" ]
79+
```
80+
81+
Once the PostgreSQL container has port forwarding enabled, it will be accessible from the Host machine at `localhost:5432`. The [PostgreSQL Documentation](https://www.postgresql.org/docs/14/index.html) has:
82+
83+
1. [An Installation Guide for PSQL](https://www.postgresql.org/docs/14/installation.html), a CLI tool to work with a PostgreSQL database.
84+
2. [Tips on populating data](https://www.postgresql.org/docs/14/populate.html) in the database.
85+
86+
If needed, you can use `postCreateCommand` to run commands after the container is created, by updating `.devcontainer/devcontainer.json` similar to what follows:
87+
88+
```json
89+
"postCreateCommand": "go version && git --version && node --version"
90+
```
91+
92+
### Adding another service
93+
94+
You can add other services to your `docker-compose.yml` file [as described in Docker's documentation](https://docs.docker.com/compose/compose-file/#service-configuration-reference). However, if you want anything running in this service to be available in the container on localhost, or want to forward the service locally, be sure to add this line to the service config:
95+
96+
```yaml
97+
# Runs the service on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
98+
network_mode: service:[$SERVICENAME]
99+
```
100+
101+
### Installing GO Dependencies
102+
103+
This definition includes the popular [PostGres Driver Library for Go](github.com/lib/pq). This is the recommended driver for use with Go, as per [GoLang Documentation](https://golangdocs.com/golang-postgresql-example).
104+
105+
If you wish to change this, you may add additional `RUN` commands in the [Go Dockerfile](.devcontainer/Dockerfile). For example:
106+
107+
```yaml
108+
# This line can be modified to add any needed additional packages
109+
RUN go get -x <github-link-for-package>
110+
```
111+
112+
## Testing the definition
113+
114+
This definition includes some test code that will help you verify it is working as expected on your system. Follow these steps:
115+
116+
1. If this is your first time using a development container, please follow the [getting started steps](https://aka.ms/vscode-remote/containers/getting-started) to set up your machine.
117+
2. Clone this repository.
118+
3. Start VS Code, press <kbd>F1</kbd>, and select **Remote-Containers: Open Folder in Container...**
119+
4. Select the `containers/go-postgres` folder.
120+
5. After the folder has opened in the container, press <kbd>F5</kbd> to start the project.
121+
6. From here the following should print out in the Debug Console:
122+
```
123+
Connected!
124+
Sending Query to Database
125+
One database in this cluster is: postgres
126+
```
127+
7. From here, you can add breakpoints or edit the contents of the `test-project` folder to do further testing.
128+
8. The Application can also be tested by running `./test.sh` from the Terminal. This will test the `hello.go` application.
129+
130+
### Debugging Security
131+
To allow C++ based debuggers to run within the Docker Containers, the [docker-compose.yml](.devcontainer/docker-compose.yml) contains the following lines which can be uncommented:
132+
133+
```yaml
134+
security_opt:
135+
- seccomp:unconfined
136+
cap_add:
137+
- SYS_PTRACE
138+
```
139+
140+
As these can create security vulnerabilities, it is advisable to not use this unless needed. This should only be used in a Debug or Dev container, not in Production.
141+
142+
## License
143+
144+
Copyright (c) Microsoft Corporation. All rights reserved.
145+
146+
Licensed under the MIT License. See [LICENSE](https://github.com/microsoft/vscode-dev-containers/blob/main/LICENSE).
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*-------------------------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
4+
*-------------------------------------------------------------------------------------------------------------*/
5+
6+
package main
7+
8+
import (
9+
"database/sql"
10+
"fmt"
11+
"os"
12+
13+
_ "github.com/lib/pq"
14+
)
15+
16+
func checkError(err error) {
17+
if err != nil {
18+
panic(err)
19+
}
20+
21+
}
22+
23+
func main() {
24+
var host string = os.Getenv("POSTGRES_HOSTNAME")
25+
var user string = os.Getenv("POSTGRES_USER")
26+
var password string = os.Getenv("POSTGRES_PASSWORD")
27+
var dbname string = os.Getenv("POSTGRES_DB")
28+
29+
psqlconn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable", host, user, password, dbname)
30+
31+
// Ready the Database connection
32+
db, err := sql.Open("postgres", psqlconn)
33+
checkError(err)
34+
35+
// close database connection after it is no longer used
36+
defer db.Close()
37+
38+
// check db
39+
err = db.Ping()
40+
checkError(err)
41+
42+
fmt.Println("Connected!")
43+
44+
fmt.Println("Sending Query to Database")
45+
rows, err := db.Query(`select datname from pg_database limit 1;`)
46+
checkError(err)
47+
48+
// close the query when no longer needed
49+
defer rows.Close()
50+
51+
for rows.Next() {
52+
var datname string
53+
54+
err = rows.Scan(&datname)
55+
checkError(err)
56+
57+
fmt.Printf("One database in this cluster is: %s \n", datname)
58+
}
59+
}

0 commit comments

Comments
 (0)