├── .gitignore
├── VERSION
├── .dockerignore
├── circle.yml
├── documents
└── examples
│ ├── streaming-server-claim0-persistentvolumeclaim.yaml
│ ├── streaming-consumer-claim0-persistentvolumeclaim.yaml
│ ├── streaming-consumer-service.yaml
│ ├── streaming-server-service.yaml
│ ├── docker-compose.yml
│ ├── index.html
│ ├── streaming-server-deployment.yaml
│ ├── streaming-consumer-deployment.yaml
│ └── full_deployment.yaml
├── assets
└── etc
│ └── nginx
│ └── nginx.conf
├── Makefile
├── Dockerfile
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /mounts
2 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 1.0-20190219
2 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | .gitignore
3 | .gitkeep
4 | circle.yml
5 | Makefile
6 | README.md
7 | VERSION
8 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | machine:
2 | services:
3 | - docker
4 | test:
5 | override:
6 | - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
7 | - make build
8 | - make test
9 | - make push
10 |
--------------------------------------------------------------------------------
/documents/examples/streaming-server-claim0-persistentvolumeclaim.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: PersistentVolumeClaim
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | io.kompose.service: streaming-server-claim0
7 | name: streaming-server-claim0
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 100Mi
14 | status: {}
15 |
--------------------------------------------------------------------------------
/documents/examples/streaming-consumer-claim0-persistentvolumeclaim.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: PersistentVolumeClaim
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | io.kompose.service: streaming-consumer-claim0
7 | name: streaming-consumer-claim0
8 | spec:
9 | accessModes:
10 | - ReadOnlyMany
11 | resources:
12 | requests:
13 | storage: 100Mi
14 | status: {}
15 |
--------------------------------------------------------------------------------
/documents/examples/streaming-consumer-service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | io.kompose.service: streaming-consumer
7 | name: streaming-consumer
8 | spec:
9 | ports:
10 | - name: "9999"
11 | port: 9999
12 | targetPort: 8080
13 | selector:
14 | io.kompose.service: streaming-consumer
15 | status:
16 | loadBalancer: {}
17 |
--------------------------------------------------------------------------------
/documents/examples/streaming-server-service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | io.kompose.service: streaming-server
7 | name: streaming-server
8 | spec:
9 | ports:
10 | - name: "1935"
11 | port: 1935
12 | targetPort: 1935
13 | - name: "8080"
14 | port: 8080
15 | targetPort: 8080
16 | selector:
17 | io.kompose.service: streaming-server
18 | status:
19 | loadBalancer: {}
20 |
--------------------------------------------------------------------------------
/documents/examples/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 |
4 | streaming-server:
5 | build: ../..
6 | image: codeworksio/streaming-server
7 | container_name: streaming-server
8 | volumes:
9 | - ../../mounts/var/lib/streaming:/var/lib/streaming:Z
10 | ports:
11 | - "1935:1935"
12 | - "8080:8080"
13 |
14 | streaming-consumer:
15 | image: codeworksio/nginx
16 | container_name: streaming-consumer
17 | volumes:
18 | - .:/var/www:ro
19 | ports:
20 | - "9999:8080"
21 |
--------------------------------------------------------------------------------
/documents/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Live Streaming
6 |
7 |
8 |
9 |
10 |
11 |
14 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/documents/examples/streaming-server-deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: extensions/v1beta1
2 | kind: Deployment
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | io.kompose.service: streaming-server
7 | name: streaming-server
8 | spec:
9 | replicas: 1
10 | strategy:
11 | type: Recreate
12 | template:
13 | metadata:
14 | creationTimestamp: null
15 | labels:
16 | io.kompose.service: streaming-server
17 | spec:
18 | containers:
19 | - image: codeworksio/streaming-server
20 | name: streaming-server
21 | ports:
22 | - containerPort: 1935
23 | - containerPort: 8080
24 | resources: {}
25 | volumeMounts:
26 | - mountPath: /var/lib/streaming
27 | name: streaming-server-claim0
28 | restartPolicy: Always
29 | volumes:
30 | - name: streaming-server-claim0
31 | persistentVolumeClaim:
32 | claimName: streaming-server-claim0
33 | status: {}
34 |
--------------------------------------------------------------------------------
/documents/examples/streaming-consumer-deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: extensions/v1beta1
2 | kind: Deployment
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | io.kompose.service: streaming-consumer
7 | name: streaming-consumer
8 | spec:
9 | replicas: 1
10 | strategy:
11 | type: Recreate
12 | template:
13 | metadata:
14 | creationTimestamp: null
15 | labels:
16 | io.kompose.service: streaming-consumer
17 | spec:
18 | containers:
19 | - image: codeworksio/nginx
20 | name: streaming-consumer
21 | ports:
22 | - containerPort: 8080
23 | resources: {}
24 | volumeMounts:
25 | - mountPath: /var/www
26 | name: streaming-consumer-claim0
27 | readOnly: true
28 | restartPolicy: Always
29 | volumes:
30 | - name: streaming-consumer-claim0
31 | persistentVolumeClaim:
32 | claimName: streaming-consumer-claim0
33 | readOnly: true
34 | status: {}
35 |
--------------------------------------------------------------------------------
/assets/etc/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | load_module modules/ngx_rtmp_module.so;
2 |
3 | worker_processes auto;
4 | events {
5 | worker_connections 1024;
6 | }
7 |
8 | rtmp {
9 | server {
10 | listen 1935;
11 | chunk_size 4000;
12 | application live {
13 | live on;
14 | hls on;
15 | hls_path /var/lib/streaming/hls/;
16 | hls_fragment 3s;
17 | hls_playlist_length 60s;
18 | deny play all;
19 | }
20 | }
21 | }
22 |
23 | http {
24 | sendfile off;
25 | tcp_nopush on;
26 | aio on;
27 | directio 512;
28 | default_type application/octet-stream;
29 | server {
30 | listen 8080;
31 | location / {
32 | add_header 'Cache-Control' 'no-cache';
33 | add_header 'Access-Control-Allow-Origin' '*' always;
34 | add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
35 | add_header 'Access-Control-Allow-Headers' 'Range';
36 | if ($request_method = 'OPTIONS') {
37 | add_header 'Access-Control-Allow-Origin' '*';
38 | add_header 'Access-Control-Allow-Headers' 'Range';
39 | add_header 'Access-Control-Max-Age' 1728000;
40 | add_header 'Content-Type' 'text/plain charset=UTF-8';
41 | add_header 'Content-Length' 0;
42 | return 204;
43 | }
44 | types {
45 | application/dash+xml mpd;
46 | application/vnd.apple.mpegurl m3u8;
47 | video/mp2t ts;
48 | }
49 | root /var/lib/streaming/;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | TARGETS := $(shell cat $(realpath $(lastword $(MAKEFILE_LIST))) | grep "^[a-z]*:" | awk '{ print $$1; }' | sed 's/://g' | grep -vE 'all|help' | paste -sd "|" -)
2 | NAME := $(subst docker-,,$(shell basename $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))))
3 | IMAGE := codeworksio/$(NAME)
4 |
5 | all: help
6 |
7 | help:
8 | echo
9 | echo "Usage:"
10 | echo
11 | echo " make $(TARGETS) [APT_PROXY|APT_PROXY_SSL=ip:port]"
12 | echo
13 |
14 | build:
15 | docker build \
16 | --build-arg APT_PROXY=$(APT_PROXY) \
17 | --build-arg APT_PROXY_SSL=$(APT_PROXY_SSL) \
18 | --build-arg IMAGE=$(IMAGE) \
19 | --build-arg BUILD_DATE=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ") \
20 | --build-arg VERSION=$(shell cat VERSION) \
21 | --build-arg VCS_REF=$(shell git rev-parse --short HEAD) \
22 | --build-arg VCS_URL=$(shell git config --get remote.origin.url) \
23 | --tag $(IMAGE):$(shell cat VERSION) \
24 | --rm .
25 | docker tag $(IMAGE):$(shell cat VERSION) $(IMAGE):latest
26 | docker rmi --force $$(docker images | grep "" | awk '{ print $$3 }') 2> /dev/null ||:
27 |
28 | start:
29 | docker run --detach --interactive --tty \
30 | --name $(NAME) \
31 | --hostname $(NAME) \
32 | --env "INIT_DEBUG=true" \
33 | --volume $(shell pwd)/mounts/var/lib/streaming:/var/lib/streaming \
34 | --publish 1935:1935 \
35 | --publish 8080:8080 \
36 | --publish 8443:8443 \
37 | $(IMAGE)
38 |
39 | stop:
40 | docker stop $(NAME) > /dev/null 2>&1 ||:
41 | docker rm $(NAME) > /dev/null 2>&1 ||:
42 |
43 | log:
44 | docker logs --follow $(NAME)
45 |
46 | test:
47 | docker run --detach --interactive --tty --name streaming-server codeworksio/streaming-server
48 | sleep 10
49 | docker ps | grep streaming-server
50 |
51 | bash:
52 | docker exec --interactive --tty \
53 | --user root \
54 | $(NAME) \
55 | /bin/bash --login ||:
56 |
57 | clean:
58 | docker rmi $(IMAGE):$(shell cat VERSION) > /dev/null 2>&1 ||:
59 | docker rmi $(IMAGE):latest > /dev/null 2>&1 ||:
60 |
61 | push:
62 | docker push $(IMAGE):$(shell cat VERSION)
63 | docker push $(IMAGE):latest
64 | sleep 10
65 | curl --request POST "https://hooks.microbadger.com/images/$(IMAGE)/o6WEpIkU6QkdRAOuZ9EcPx6djOo="
66 |
67 | .SILENT:
68 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM codeworksio/nginx:1.15.8-20190219
2 |
3 | ARG APT_PROXY
4 | ARG APT_PROXY_SSL
5 | ENV NGINX_RTMP_MODULE_VERSION="1.2.1"
6 |
7 | RUN set -ex; \
8 | \
9 | buildDependencies="\
10 | build-essential \
11 | libpcre3-dev \
12 | libssl-dev \
13 | zlib1g-dev \
14 | "; \
15 | if [ -n "$APT_PROXY" ]; then echo "Acquire::http { Proxy \"http://${APT_PROXY}\"; };" > /etc/apt/apt.conf.d/00proxy; fi; \
16 | if [ -n "$APT_PROXY_SSL" ]; then echo "Acquire::https { Proxy \"https://${APT_PROXY_SSL}\"; };" > /etc/apt/apt.conf.d/00proxy; fi; \
17 | apt-get --yes update; \
18 | apt-get --yes install \
19 | $buildDependencies \
20 | ffmpeg \
21 | ; \
22 | cd /tmp; \
23 | curl -L "https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz" -o nginx-$NGINX_VERSION.tar.gz; \
24 | tar -xf nginx-$NGINX_VERSION.tar.gz; \
25 | curl -L "https://github.com/arut/nginx-rtmp-module/archive/v${NGINX_RTMP_MODULE_VERSION}.tar.gz" -o nginx-rtmp-module-$NGINX_RTMP_MODULE_VERSION.tar.gz; \
26 | tar -xf nginx-rtmp-module-$NGINX_RTMP_MODULE_VERSION.tar.gz; \
27 | \
28 | cd /tmp/nginx-$NGINX_VERSION; \
29 | ./configure \
30 | $(nginx -V 2>&1 | grep 'configure arguments:' | sed 's/configure arguments://g') \
31 | --add-dynamic-module=/tmp/nginx-rtmp-module-$NGINX_RTMP_MODULE_VERSION; \
32 | make modules; \
33 | mkdir -p /usr/local/nginx/modules; \
34 | cp -v objs/ngx_rtmp_module.so /usr/local/nginx/modules; \
35 | \
36 | mkdir -p \
37 | /var/lib/streaming/hls \
38 | /var/lib/streaming/dash; \
39 | chown -R $SYSTEM_USER:$SYSTEM_USER \
40 | /usr/local/nginx/modules \
41 | /var/lib/streaming; \
42 | \
43 | apt-get purge --yes --auto-remove $buildDependencies; \
44 | rm -rf /tmp/* /var/tmp/* /var/lib/apt/lists/* /var/cache/apt/*; \
45 | rm -f /etc/apt/apt.conf.d/00proxy
46 |
47 | COPY assets/ /
48 |
49 | VOLUME [ "/var/lib/streaming" ]
50 | EXPOSE 1935 8080 8443
51 | CMD [ "nginx", "-g", "daemon off;" ]
52 |
53 | ### METADATA ###################################################################
54 |
55 | ARG IMAGE
56 | ARG BUILD_DATE
57 | ARG VERSION
58 | ARG VCS_REF
59 | ARG VCS_URL
60 | LABEL \
61 | org.label-schema.name=$IMAGE \
62 | org.label-schema.build-date=$BUILD_DATE \
63 | org.label-schema.version=$VERSION \
64 | org.label-schema.vcs-ref=$VCS_REF \
65 | org.label-schema.vcs-url=$VCS_URL \
66 | org.label-schema.schema-version="1.0"
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://circleci.com/gh/codeworksio/docker-streaming-server) [](http://microbadger.com/images/codeworksio/streaming-server) [](http://microbadger.com/images/codeworksio/streaming-server) [](http://microbadger.com/images/codeworksio/streaming-server) [](https://hub.docker.com/r/codeworksio/streaming-server/)
2 |
3 | Docker Streaming Server
4 | =======================
5 |
6 | A robust way of streaming media content live using the [NGINX](https://nginx.org/) web server and its [RTMP](https://github.com/tiangolo/nginx-rtmp-docker) module.
7 |
8 | Installation
9 | ------------
10 |
11 | Builds of the image are available on [Docker Hub](https://hub.docker.com/r/codeworksio/streaming-server/).
12 |
13 | docker pull codeworksio/streaming-server
14 |
15 | Alternatively you can build the image yourself.
16 |
17 | docker build --tag codeworksio/streaming-server \
18 | github.com/codeworksio/docker-streaming-server
19 |
20 | Quickstart
21 | ----------
22 |
23 | Start container using:
24 |
25 | docker run --detach --restart always \
26 | --name streaming-server \
27 | --hostname streaming-server \
28 | --publish 1935:1935 \
29 | --publish 8080:8080 \
30 | --publish 8443:8443 \
31 | codeworksio/streaming-server
32 |
33 | Example
34 | -------
35 |
36 | 1. Start the streaming server and consumer from the command line
37 |
38 | ```bash
39 | cd ./documents/examples
40 | docker-compose up -d
41 | ```
42 |
43 | 2. Use [Open Broadcaster Software](https://obsproject.com/) to stream your content
44 |
45 | * Add media source `Sources` > `+` > `Video Capture Device`
46 | * Configure streaming server `Controls` > `Settings` > `Stream`
47 | - Stream type: `Custom Streaming Server`
48 | - URL: `rtmp://localhost/live`
49 | - Stream key: `test`
50 | * Press `Start Streaming` button
51 |
52 | 3. Go to `http://localhost:9999` URL address in your browser to view the media live.
53 |
54 | See
55 | ---
56 |
57 | * [Open Broadcaster Software post](https://obsproject.com/forum/resources/how-to-set-up-your-own-private-streaming-server-server-using-nginx.50/)
58 |
--------------------------------------------------------------------------------
/documents/examples/full_deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: extensions/v1beta1
2 | kind: Deployment
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | io.kompose.service: streaming-server
7 | name: streaming-server
8 | spec:
9 | replicas: 1
10 | strategy:
11 | type: Recreate
12 | template:
13 | metadata:
14 | creationTimestamp: null
15 | labels:
16 | io.kompose.service: streaming-server
17 | spec:
18 | containers:
19 | - image: codeworksio/streaming-server
20 | name: streaming-server
21 | ports:
22 | - containerPort: 1935
23 | - containerPort: 8080
24 | resources: {}
25 | volumeMounts:
26 | - mountPath: /var/lib/streaming
27 | name: streaming-server-claim0
28 | restartPolicy: Always
29 | volumes:
30 | - name: streaming-server-claim0
31 | persistentVolumeClaim:
32 | claimName: streaming-server-claim0
33 | status: {}
34 |
35 | ---
36 | apiVersion: v1
37 | kind: Service
38 | metadata:
39 | creationTimestamp: null
40 | labels:
41 | io.kompose.service: streaming-server
42 | name: streaming-server
43 | spec:
44 | ports:
45 | - port: 1935
46 | targetPort: 1935
47 | - port: 8080
48 | targetPort: 8080
49 | selector:
50 | io.kompose.service: streaming-server
51 | status:
52 | loadBalancer: {}
53 |
54 | ---
55 | apiVersion: v1
56 | kind: PersistentVolumeClaim
57 | metadata:
58 | creationTimestamp: null
59 | labels:
60 | io.kompose.service: streaming-server-claim0
61 | name: streaming-server-claim0
62 | spec:
63 | accessModes:
64 | - ReadWriteOnce
65 | resources:
66 | requests:
67 | storage: 100Mi
68 | status: {}
69 |
70 | ---
71 | apiVersion: extensions/v1beta1
72 | kind: Deployment
73 | metadata:
74 | creationTimestamp: null
75 | labels:
76 | io.kompose.service: streaming-consumer
77 | name: streaming-consumer
78 | spec:
79 | replicas: 1
80 | strategy:
81 | type: Recreate
82 | template:
83 | metadata:
84 | creationTimestamp: null
85 | labels:
86 | io.kompose.service: streaming-consumer
87 | spec:
88 | containers:
89 | - image: codeworksio/nginx
90 | name: streaming-consumer
91 | ports:
92 | - containerPort: 8080
93 | resources: {}
94 | volumeMounts:
95 | - mountPath: /var/www
96 | name: streaming-consumer-claim0
97 | readOnly: true
98 | restartPolicy: Always
99 | volumes:
100 | - name: streaming-consumer-claim0
101 | persistentVolumeClaim:
102 | claimName: streaming-consumer-claim0
103 | readOnly: true
104 | status: {}
105 |
106 | ---
107 | apiVersion: v1
108 | kind: Service
109 | metadata:
110 | creationTimestamp: null
111 | labels:
112 | io.kompose.service: streaming-consumer
113 | name: streaming-consumer
114 | spec:
115 | ports:
116 | - port: 9999
117 | targetPort: 8080
118 | selector:
119 | io.kompose.service: streaming-consumer
120 | status:
121 | loadBalancer: {}
122 |
123 | ---
124 | apiVersion: v1
125 | kind: PersistentVolumeClaim
126 | metadata:
127 | creationTimestamp: null
128 | labels:
129 | io.kompose.service: streaming-consumer-claim0
130 | name: streaming-consumer-claim0
131 | spec:
132 | accessModes:
133 | - ReadOnlyMany
134 | resources:
135 | requests:
136 | storage: 100Mi
137 | status: {}
--------------------------------------------------------------------------------